@apimatic/cli 1.5.0 → 2.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +128 -212
- package/apimatic.schema.json +550 -0
- package/lib/actions/action-result.js +3 -0
- package/lib/actions/action-result.js.map +1 -1
- package/lib/actions/api/transform.js +36 -33
- package/lib/actions/api/transform.js.map +1 -1
- package/lib/actions/api/validate.d.ts +9 -6
- package/lib/actions/api/validate.js +44 -38
- package/lib/actions/api/validate.js.map +1 -1
- package/lib/actions/auth/login.js +7 -4
- package/lib/actions/auth/login.js.map +1 -1
- package/lib/actions/auth/logout.js +2 -1
- package/lib/actions/auth/logout.js.map +1 -1
- package/lib/actions/auth/status.js +5 -3
- package/lib/actions/auth/status.js.map +1 -1
- package/lib/actions/plugin/generate.d.ts +5 -1
- package/lib/actions/plugin/generate.js +83 -56
- package/lib/actions/plugin/generate.js.map +1 -1
- package/lib/actions/plugin/publish.d.ts +2 -1
- package/lib/actions/plugin/publish.js +34 -37
- package/lib/actions/plugin/publish.js.map +1 -1
- package/lib/actions/plugin/record-metadata.d.ts +3 -2
- package/lib/actions/plugin/record-metadata.js +33 -30
- package/lib/actions/plugin/record-metadata.js.map +1 -1
- package/lib/actions/portal/generate.d.ts +8 -6
- package/lib/actions/portal/generate.js +50 -61
- package/lib/actions/portal/generate.js.map +1 -1
- package/lib/actions/portal/prepare-project.d.ts +25 -0
- package/lib/actions/portal/prepare-project.js +68 -0
- package/lib/actions/portal/prepare-project.js.map +1 -0
- package/lib/actions/portal/serve.d.ts +21 -6
- package/lib/actions/portal/serve.js +170 -153
- package/lib/actions/portal/serve.js.map +1 -1
- package/lib/actions/publishing/profile/list.js +4 -2
- package/lib/actions/publishing/profile/list.js.map +1 -1
- package/lib/actions/quickstart.d.ts +23 -5
- package/lib/actions/quickstart.js +222 -21
- package/lib/actions/quickstart.js.map +1 -1
- package/lib/actions/sdk/generate.d.ts +4 -7
- package/lib/actions/sdk/generate.js +53 -93
- package/lib/actions/sdk/generate.js.map +1 -1
- package/lib/actions/sdk/publish/interactive.d.ts +4 -3
- package/lib/actions/sdk/publish/interactive.js +96 -97
- package/lib/actions/sdk/publish/interactive.js.map +1 -1
- package/lib/actions/sdk/publish/non-interactive.d.ts +4 -2
- package/lib/actions/sdk/publish/non-interactive.js +91 -90
- package/lib/actions/sdk/publish/non-interactive.js.map +1 -1
- package/lib/actions/sdk/publish.d.ts +3 -2
- package/lib/actions/sdk/publish.js +55 -53
- package/lib/actions/sdk/publish.js.map +1 -1
- package/lib/actions/sdk/record-published-sdk.d.ts +14 -0
- package/lib/actions/sdk/record-published-sdk.js +57 -0
- package/lib/actions/sdk/record-published-sdk.js.map +1 -0
- package/lib/client-utils/auth-manager.js +1 -1
- package/lib/client-utils/auth-manager.js.map +1 -1
- package/lib/commands/api/transform.d.ts +1 -1
- package/lib/commands/api/transform.js +44 -40
- package/lib/commands/api/transform.js.map +1 -1
- package/lib/commands/api/validate.js +16 -16
- package/lib/commands/api/validate.js.map +1 -1
- package/lib/commands/auth/login.js +14 -15
- package/lib/commands/auth/login.js.map +1 -1
- package/lib/commands/auth/logout.js +5 -6
- package/lib/commands/auth/logout.js.map +1 -1
- package/lib/commands/auth/status.js +4 -5
- package/lib/commands/auth/status.js.map +1 -1
- package/lib/commands/plugin/generate.d.ts +3 -3
- package/lib/commands/plugin/generate.js +20 -20
- package/lib/commands/plugin/generate.js.map +1 -1
- package/lib/commands/plugin/publish.js +18 -18
- package/lib/commands/plugin/publish.js.map +1 -1
- package/lib/commands/portal/generate.d.ts +9 -8
- package/lib/commands/portal/generate.js +36 -27
- package/lib/commands/portal/generate.js.map +1 -1
- package/lib/commands/portal/serve.d.ts +7 -9
- package/lib/commands/portal/serve.js +41 -44
- package/lib/commands/portal/serve.js.map +1 -1
- package/lib/commands/publishing/profile/list.js +8 -12
- package/lib/commands/publishing/profile/list.js.map +1 -1
- package/lib/commands/quickstart.d.ts +5 -5
- package/lib/commands/quickstart.js +18 -24
- package/lib/commands/quickstart.js.map +1 -1
- package/lib/commands/sdk/generate.d.ts +5 -7
- package/lib/commands/sdk/generate.js +58 -70
- package/lib/commands/sdk/generate.js.map +1 -1
- package/lib/commands/sdk/publish.d.ts +6 -7
- package/lib/commands/sdk/publish.js +66 -60
- package/lib/commands/sdk/publish.js.map +1 -1
- package/lib/hooks/node-version.d.ts +3 -0
- package/lib/hooks/node-version.js +12 -0
- package/lib/hooks/node-version.js.map +1 -0
- package/lib/hooks/not-found.js +2 -3
- package/lib/hooks/not-found.js.map +1 -1
- package/lib/hooks/utils.d.ts +4 -2
- package/lib/hooks/utils.js +2 -2
- package/lib/hooks/utils.js.map +1 -1
- package/lib/infrastructure/env-info.d.ts +3 -0
- package/lib/infrastructure/env-info.js +13 -6
- package/lib/infrastructure/env-info.js.map +1 -1
- package/lib/infrastructure/file-service.d.ts +35 -8
- package/lib/infrastructure/file-service.js +149 -53
- package/lib/infrastructure/file-service.js.map +1 -1
- package/lib/infrastructure/file-watch-service.d.ts +40 -0
- package/lib/infrastructure/file-watch-service.js +167 -0
- package/lib/infrastructure/file-watch-service.js.map +1 -0
- package/lib/infrastructure/generation-status-poller.d.ts +8 -7
- package/lib/infrastructure/generation-status-poller.js +20 -12
- package/lib/infrastructure/generation-status-poller.js.map +1 -1
- package/lib/infrastructure/launcher-service.js +6 -6
- package/lib/infrastructure/launcher-service.js.map +1 -1
- package/lib/infrastructure/network-service.d.ts +3 -0
- package/lib/infrastructure/network-service.js +15 -1
- package/lib/infrastructure/network-service.js.map +1 -1
- package/lib/infrastructure/portal-build-service.d.ts +19 -0
- package/lib/infrastructure/portal-build-service.js +58 -0
- package/lib/infrastructure/portal-build-service.js.map +1 -0
- package/lib/infrastructure/portal-dev-server-service.d.ts +29 -0
- package/lib/infrastructure/portal-dev-server-service.js +135 -0
- package/lib/infrastructure/portal-dev-server-service.js.map +1 -0
- package/lib/infrastructure/portal-pages-service.d.ts +17 -0
- package/lib/infrastructure/portal-pages-service.js +103 -0
- package/lib/infrastructure/portal-pages-service.js.map +1 -0
- package/lib/infrastructure/portal-project-service.d.ts +77 -0
- package/lib/infrastructure/portal-project-service.js +309 -0
- package/lib/infrastructure/portal-project-service.js.map +1 -0
- package/lib/infrastructure/service-error.d.ts +1 -0
- package/lib/infrastructure/service-error.js +39 -41
- package/lib/infrastructure/service-error.js.map +1 -1
- package/lib/infrastructure/services/api-client-factory.js +15 -13
- package/lib/infrastructure/services/api-client-factory.js.map +1 -1
- package/lib/infrastructure/services/api-service.d.ts +7 -5
- package/lib/infrastructure/services/api-service.js +28 -20
- package/lib/infrastructure/services/api-service.js.map +1 -1
- package/lib/infrastructure/services/auth-service.js +4 -9
- package/lib/infrastructure/services/auth-service.js.map +1 -1
- package/lib/infrastructure/services/file-download-service.js +3 -3
- package/lib/infrastructure/services/file-download-service.js.map +1 -1
- package/lib/infrastructure/services/plugin-service.d.ts +1 -8
- package/lib/infrastructure/services/plugin-service.js +11 -22
- package/lib/infrastructure/services/plugin-service.js.map +1 -1
- package/lib/infrastructure/services/portal-artifacts-service.d.ts +44 -0
- package/lib/infrastructure/services/portal-artifacts-service.js +268 -0
- package/lib/infrastructure/services/portal-artifacts-service.js.map +1 -0
- package/lib/infrastructure/services/portal-authorization-service.d.ts +22 -0
- package/lib/infrastructure/services/portal-authorization-service.js +23 -0
- package/lib/infrastructure/services/portal-authorization-service.js.map +1 -0
- package/lib/infrastructure/services/publishing-api-service.d.ts +1 -1
- package/lib/infrastructure/services/publishing-api-service.js +11 -15
- package/lib/infrastructure/services/publishing-api-service.js.map +1 -1
- package/lib/infrastructure/services/sdk-generation-service.d.ts +21 -0
- package/lib/infrastructure/services/sdk-generation-service.js +118 -0
- package/lib/infrastructure/services/sdk-generation-service.js.map +1 -0
- package/lib/infrastructure/services/telemetry-service.js +5 -4
- package/lib/infrastructure/services/telemetry-service.js.map +1 -1
- package/lib/infrastructure/services/transformation-service.js +29 -32
- package/lib/infrastructure/services/transformation-service.js.map +1 -1
- package/lib/infrastructure/services/validation-service.d.ts +12 -53
- package/lib/infrastructure/services/validation-service.js +24 -199
- package/lib/infrastructure/services/validation-service.js.map +1 -1
- package/lib/infrastructure/timer-extensions.d.ts +2 -0
- package/lib/infrastructure/timer-extensions.js +10 -0
- package/lib/infrastructure/timer-extensions.js.map +1 -0
- package/lib/infrastructure/tmp-extensions.d.ts +31 -1
- package/lib/infrastructure/tmp-extensions.js +86 -3
- package/lib/infrastructure/tmp-extensions.js.map +1 -1
- package/lib/infrastructure/zip-service.js +2 -2
- package/lib/infrastructure/zip-service.js.map +1 -1
- package/lib/prompts/api/validate.d.ts +6 -7
- package/lib/prompts/api/validate.js +12 -12
- package/lib/prompts/api/validate.js.map +1 -1
- package/lib/prompts/format.d.ts +4 -0
- package/lib/prompts/format.js +5 -0
- package/lib/prompts/format.js.map +1 -1
- package/lib/prompts/plugin/generate.d.ts +17 -12
- package/lib/prompts/plugin/generate.js +94 -44
- package/lib/prompts/plugin/generate.js.map +1 -1
- package/lib/prompts/plugin/publish.d.ts +2 -1
- package/lib/prompts/plugin/publish.js +8 -7
- package/lib/prompts/plugin/publish.js.map +1 -1
- package/lib/prompts/plugin/record-metadata.d.ts +1 -0
- package/lib/prompts/plugin/record-metadata.js +10 -7
- package/lib/prompts/plugin/record-metadata.js.map +1 -1
- package/lib/prompts/portal/artifacts.d.ts +8 -0
- package/lib/prompts/portal/artifacts.js +26 -0
- package/lib/prompts/portal/artifacts.js.map +1 -0
- package/lib/prompts/portal/authorization.d.ts +6 -0
- package/lib/prompts/portal/authorization.js +29 -0
- package/lib/prompts/portal/authorization.js.map +1 -0
- package/lib/prompts/portal/code-samples.d.ts +1 -0
- package/lib/prompts/portal/code-samples.js +9 -0
- package/lib/prompts/portal/code-samples.js.map +1 -0
- package/lib/prompts/portal/generate.d.ts +14 -9
- package/lib/prompts/portal/generate.js +48 -26
- package/lib/prompts/portal/generate.js.map +1 -1
- package/lib/prompts/portal/prepare-project.d.ts +20 -0
- package/lib/prompts/portal/prepare-project.js +36 -0
- package/lib/prompts/portal/prepare-project.js.map +1 -0
- package/lib/prompts/portal/serve.d.ts +32 -12
- package/lib/prompts/portal/serve.js +102 -39
- package/lib/prompts/portal/serve.js.map +1 -1
- package/lib/prompts/portal/source.d.ts +26 -0
- package/lib/prompts/portal/source.js +253 -0
- package/lib/prompts/portal/source.js.map +1 -0
- package/lib/prompts/prompt.d.ts +11 -3
- package/lib/prompts/prompt.js +39 -15
- package/lib/prompts/prompt.js.map +1 -1
- package/lib/prompts/quickstart.d.ts +46 -3
- package/lib/prompts/quickstart.js +199 -12
- package/lib/prompts/quickstart.js.map +1 -1
- package/lib/prompts/sdk/generate.d.ts +15 -13
- package/lib/prompts/sdk/generate.js +29 -32
- package/lib/prompts/sdk/generate.js.map +1 -1
- package/lib/prompts/sdk/publish/interactive.d.ts +10 -6
- package/lib/prompts/sdk/publish/interactive.js +26 -24
- package/lib/prompts/sdk/publish/interactive.js.map +1 -1
- package/lib/prompts/sdk/publish/non-interactive.d.ts +2 -1
- package/lib/prompts/sdk/publish/non-interactive.js +5 -4
- package/lib/prompts/sdk/publish/non-interactive.js.map +1 -1
- package/lib/prompts/sdk/publish.d.ts +3 -3
- package/lib/prompts/sdk/publish.js +13 -17
- package/lib/prompts/sdk/publish.js.map +1 -1
- package/lib/prompts/sdk/record-published-sdk.d.ts +7 -0
- package/lib/prompts/sdk/record-published-sdk.js +26 -0
- package/lib/prompts/sdk/record-published-sdk.js.map +1 -0
- package/lib/types/apimatic-config/document.d.ts +70 -0
- package/lib/types/apimatic-config/document.js +167 -0
- package/lib/types/apimatic-config/document.js.map +1 -0
- package/lib/types/apimatic-config/languages-block.d.ts +39 -0
- package/lib/types/apimatic-config/languages-block.js +58 -0
- package/lib/types/apimatic-config/languages-block.js.map +1 -0
- package/lib/types/apimatic-config-context.d.ts +48 -0
- package/lib/types/apimatic-config-context.js +121 -0
- package/lib/types/apimatic-config-context.js.map +1 -0
- package/lib/types/build/build.d.ts +1 -89
- package/lib/types/build/build.js +6 -161
- package/lib/types/build/build.js.map +1 -1
- package/lib/types/events/domain-event.js +3 -0
- package/lib/types/events/domain-event.js.map +1 -1
- package/lib/types/events/quickstart-completed.js +3 -3
- package/lib/types/events/quickstart-completed.js.map +1 -1
- package/lib/types/events/quickstart-initiated.js +3 -3
- package/lib/types/events/quickstart-initiated.js.map +1 -1
- package/lib/types/events/sdk-publish-validation-failed.js +1 -1
- package/lib/types/events/sdk-publish-validation-failed.js.map +1 -1
- package/lib/types/file/directory.d.ts +4 -9
- package/lib/types/file/directory.js +17 -65
- package/lib/types/file/directory.js.map +1 -1
- package/lib/types/file/directoryPath.d.ts +17 -0
- package/lib/types/file/directoryPath.js +47 -2
- package/lib/types/file/directoryPath.js.map +1 -1
- package/lib/types/file/fileName.d.ts +8 -0
- package/lib/types/file/fileName.js +28 -6
- package/lib/types/file/fileName.js.map +1 -1
- package/lib/types/file/filePath.d.ts +18 -2
- package/lib/types/file/filePath.js +39 -4
- package/lib/types/file/filePath.js.map +1 -1
- package/lib/types/file/resource-input.js +1 -2
- package/lib/types/file/resource-input.js.map +1 -1
- package/lib/types/file/urlPath.js +2 -1
- package/lib/types/file/urlPath.js.map +1 -1
- package/lib/types/flags-provider.js +22 -22
- package/lib/types/flags-provider.js.map +1 -1
- package/lib/types/package-settings-context.js +2 -1
- package/lib/types/package-settings-context.js.map +1 -1
- package/lib/types/plugin/plugin-config.d.ts +10 -50
- package/lib/types/plugin/plugin-config.js +7 -1
- package/lib/types/plugin/plugin-config.js.map +1 -1
- package/lib/types/plugin-config-context.d.ts +30 -37
- package/lib/types/plugin-config-context.js +108 -139
- package/lib/types/plugin-config-context.js.map +1 -1
- package/lib/types/plugin-context.js +3 -2
- package/lib/types/plugin-context.js.map +1 -1
- package/lib/types/portal/code-samples.d.ts +27 -0
- package/lib/types/portal/code-samples.js +67 -0
- package/lib/types/portal/code-samples.js.map +1 -0
- package/lib/types/portal/config/ai-config.d.ts +15 -0
- package/lib/types/portal/config/ai-config.js +26 -0
- package/lib/types/portal/config/ai-config.js.map +1 -0
- package/lib/types/portal/config/brand-config.d.ts +55 -0
- package/lib/types/portal/config/brand-config.js +105 -0
- package/lib/types/portal/config/brand-config.js.map +1 -0
- package/lib/types/portal/config/color.d.ts +19 -0
- package/lib/types/portal/config/color.js +43 -0
- package/lib/types/portal/config/color.js.map +1 -0
- package/lib/types/portal/config/fields.d.ts +23 -0
- package/lib/types/portal/config/fields.js +67 -0
- package/lib/types/portal/config/fields.js.map +1 -0
- package/lib/types/portal/config/link.d.ts +18 -0
- package/lib/types/portal/config/link.js +72 -0
- package/lib/types/portal/config/link.js.map +1 -0
- package/lib/types/portal/config/navigation-config.d.ts +13 -0
- package/lib/types/portal/config/navigation-config.js +30 -0
- package/lib/types/portal/config/navigation-config.js.map +1 -0
- package/lib/types/portal/config/site-config.d.ts +32 -0
- package/lib/types/portal/config/site-config.js +88 -0
- package/lib/types/portal/config/site-config.js.map +1 -0
- package/lib/types/portal/config/static-asset.d.ts +25 -0
- package/lib/types/portal/config/static-asset.js +77 -0
- package/lib/types/portal/config/static-asset.js.map +1 -0
- package/lib/types/portal/content-notices.d.ts +20 -0
- package/lib/types/portal/content-notices.js +2 -0
- package/lib/types/portal/content-notices.js.map +1 -0
- package/lib/types/portal/content-tree.d.ts +103 -0
- package/lib/types/portal/content-tree.js +344 -0
- package/lib/types/portal/content-tree.js.map +1 -0
- package/lib/types/portal/endpoint.d.ts +6 -0
- package/lib/types/portal/endpoint.js +12 -0
- package/lib/types/portal/endpoint.js.map +1 -0
- package/lib/types/portal/generated-pages.d.ts +68 -0
- package/lib/types/portal/generated-pages.js +111 -0
- package/lib/types/portal/generated-pages.js.map +1 -0
- package/lib/types/portal/generation-status.d.ts +31 -0
- package/lib/types/portal/generation-status.js +26 -0
- package/lib/types/portal/generation-status.js.map +1 -0
- package/lib/types/portal/openapi-document.d.ts +48 -0
- package/lib/types/portal/openapi-document.js +138 -0
- package/lib/types/portal/openapi-document.js.map +1 -0
- package/lib/types/portal/page-fragments.d.ts +13 -0
- package/lib/types/portal/page-fragments.js +24 -0
- package/lib/types/portal/page-fragments.js.map +1 -0
- package/lib/types/portal/page-template.d.ts +15 -0
- package/lib/types/portal/page-template.js +64 -0
- package/lib/types/portal/page-template.js.map +1 -0
- package/lib/types/portal/page.d.ts +24 -0
- package/lib/types/portal/page.js +100 -0
- package/lib/types/portal/page.js.map +1 -0
- package/lib/types/portal/portal-artifacts.d.ts +25 -0
- package/lib/types/portal/portal-artifacts.js +30 -0
- package/lib/types/portal/portal-artifacts.js.map +1 -0
- package/lib/types/portal/portal-config.d.ts +69 -0
- package/lib/types/portal/portal-config.js +105 -0
- package/lib/types/portal/portal-config.js.map +1 -0
- package/lib/types/portal/portal-downloads.d.ts +8 -0
- package/lib/types/portal/portal-downloads.js +14 -0
- package/lib/types/portal/portal-downloads.js.map +1 -0
- package/lib/types/portal/portal-languages.d.ts +15 -0
- package/lib/types/portal/portal-languages.js +45 -0
- package/lib/types/portal/portal-languages.js.map +1 -0
- package/lib/types/portal/portal-navigation.d.ts +65 -0
- package/lib/types/portal/portal-navigation.js +217 -0
- package/lib/types/portal/portal-navigation.js.map +1 -0
- package/lib/types/portal/portal-sdk.d.ts +15 -0
- package/lib/types/portal/portal-sdk.js +28 -0
- package/lib/types/portal/portal-sdk.js.map +1 -0
- package/lib/types/portal/portal-source.d.ts +129 -0
- package/lib/types/portal/portal-source.js +2 -0
- package/lib/types/portal/portal-source.js.map +1 -0
- package/lib/types/portal/portal-stylesheet.d.ts +19 -0
- package/lib/types/portal/portal-stylesheet.js +40 -0
- package/lib/types/portal/portal-stylesheet.js.map +1 -0
- package/lib/types/portal/portal-tabs.d.ts +33 -0
- package/lib/types/portal/portal-tabs.js +38 -0
- package/lib/types/portal/portal-tabs.js.map +1 -0
- package/lib/types/portal/preview-config.d.ts +20 -0
- package/lib/types/portal/preview-config.js +32 -0
- package/lib/types/portal/preview-config.js.map +1 -0
- package/lib/types/portal/preview-content.d.ts +18 -0
- package/lib/types/portal/preview-content.js +50 -0
- package/lib/types/portal/preview-content.js.map +1 -0
- package/lib/types/portal/published-package.d.ts +12 -0
- package/lib/types/portal/published-package.js +35 -0
- package/lib/types/portal/published-package.js.map +1 -0
- package/lib/types/portal/unknown-fields.d.ts +5 -0
- package/lib/types/portal/unknown-fields.js +10 -0
- package/lib/types/portal/unknown-fields.js.map +1 -0
- package/lib/types/portal-context.d.ts +38 -6
- package/lib/types/portal-context.js +71 -24
- package/lib/types/portal-context.js.map +1 -1
- package/lib/types/portal-source-context.d.ts +77 -0
- package/lib/types/portal-source-context.js +408 -0
- package/lib/types/portal-source-context.js.map +1 -0
- package/lib/types/project-context.d.ts +49 -0
- package/lib/types/project-context.js +151 -0
- package/lib/types/project-context.js.map +1 -0
- package/lib/types/project-layout.d.ts +9 -0
- package/lib/types/project-layout.js +10 -0
- package/lib/types/project-layout.js.map +1 -0
- package/lib/types/publish/package-settings-configuration.d.ts +2 -0
- package/lib/types/publish/profile-id.js +1 -0
- package/lib/types/publish/profile-id.js.map +1 -1
- package/lib/types/publish/publishing-profile.d.ts +3 -1
- package/lib/types/publish/publishing-profile.js +33 -15
- package/lib/types/publish/publishing-profile.js.map +1 -1
- package/lib/types/publish/publishing-profiles.js +2 -1
- package/lib/types/publish/publishing-profiles.js.map +1 -1
- package/lib/types/publish/version.js +1 -0
- package/lib/types/publish/version.js.map +1 -1
- package/lib/types/resource-context.js +3 -2
- package/lib/types/resource-context.js.map +1 -1
- package/lib/types/sdk/generate.d.ts +22 -16
- package/lib/types/sdk/generate.js +64 -41
- package/lib/types/sdk/generate.js.map +1 -1
- package/lib/types/sdk/stability-choice.d.ts +12 -0
- package/lib/types/sdk/stability-choice.js +24 -0
- package/lib/types/sdk/stability-choice.js.map +1 -0
- package/lib/types/sdk-context.d.ts +4 -5
- package/lib/types/sdk-context.js +10 -18
- package/lib/types/sdk-context.js.map +1 -1
- package/lib/types/spec-context.d.ts +5 -4
- package/lib/types/spec-context.js +9 -8
- package/lib/types/spec-context.js.map +1 -1
- package/lib/types/temp-context.d.ts +1 -1
- package/lib/types/temp-context.js +5 -4
- package/lib/types/temp-context.js.map +1 -1
- package/lib/types/transform-context.d.ts +9 -5
- package/lib/types/transform-context.js +21 -18
- package/lib/types/transform-context.js.map +1 -1
- package/lib/utils/error-utils.d.ts +2 -0
- package/lib/utils/error-utils.js +5 -0
- package/lib/utils/error-utils.js.map +1 -0
- package/lib/utils/json-utils.d.ts +2 -0
- package/lib/utils/json-utils.js +4 -0
- package/lib/utils/json-utils.js.map +1 -0
- package/lib/utils/string-utils.d.ts +8 -1
- package/lib/utils/string-utils.js +13 -26
- package/lib/utils/string-utils.js.map +1 -1
- package/lib/utils/utils.d.ts +1 -3
- package/lib/utils/utils.js +12 -40
- package/lib/utils/utils.js.map +1 -1
- package/oclif.manifest.json +69 -357
- package/package.json +47 -25
- package/portal-pages/context-plugin.mdx +26 -0
- package/portal-pages/sdk.mdx +8 -0
- package/portal-pages/sdks.mdx +11 -0
- package/portal-template/NOTICE +37 -0
- package/portal-template/downloads.ts +41 -0
- package/portal-template/generated-pages-reload.ts +51 -0
- package/portal-template/package.json +11 -0
- package/portal-template/portal-config.ts +32 -0
- package/portal-template/prerender-pages.ts +81 -0
- package/portal-template/spec-reload.ts +26 -0
- package/portal-template/src/components/api-page.tsx +15 -0
- package/portal-template/src/components/code-block.tsx +9 -0
- package/portal-template/src/components/command-block.tsx +50 -0
- package/portal-template/src/components/example-layout.tsx +99 -0
- package/portal-template/src/components/logos.tsx +127 -0
- package/portal-template/src/components/mdx.tsx +28 -0
- package/portal-template/src/components/not-found.tsx +11 -0
- package/portal-template/src/components/plugin-install.tsx +22 -0
- package/portal-template/src/components/plugin-support.tsx +53 -0
- package/portal-template/src/components/sdk-actions.tsx +79 -0
- package/portal-template/src/components/sdk-cards.tsx +100 -0
- package/portal-template/src/components/search.tsx +41 -0
- package/portal-template/src/components/usage-tabs.tsx +92 -0
- package/portal-template/src/lib/code-samples.server.ts +40 -0
- package/portal-template/src/lib/code-samples.ts +43 -0
- package/portal-template/src/lib/code-titles.ts +29 -0
- package/portal-template/src/lib/install-command.ts +13 -0
- package/portal-template/src/lib/json.ts +5 -0
- package/portal-template/src/lib/layout.shared.tsx +41 -0
- package/portal-template/src/lib/layout.tsx +16 -0
- package/portal-template/src/lib/llms.server.ts +54 -0
- package/portal-template/src/lib/media-adapters.ts +34 -0
- package/portal-template/src/lib/navigation.ts +406 -0
- package/portal-template/src/lib/openapi-bundle.server.ts +343 -0
- package/portal-template/src/lib/openapi-filter.ts +191 -0
- package/portal-template/src/lib/openapi-labels.ts +15 -0
- package/portal-template/src/lib/openapi-methods.ts +12 -0
- package/portal-template/src/lib/openapi-section.server.ts +280 -0
- package/portal-template/src/lib/openapi-slim.ts +202 -0
- package/portal-template/src/lib/openapi.server.ts +16 -0
- package/portal-template/src/lib/portal-types.ts +36 -0
- package/portal-template/src/lib/portal.server.ts +13 -0
- package/portal-template/src/lib/portal.ts +11 -0
- package/portal-template/src/lib/rehype-code-titles.ts +53 -0
- package/portal-template/src/lib/request-examples.ts +72 -0
- package/portal-template/src/lib/seo.ts +21 -0
- package/portal-template/src/lib/shared.ts +51 -0
- package/portal-template/src/lib/shiki-bundle.ts +104 -0
- package/portal-template/src/lib/sitemap.server.ts +20 -0
- package/portal-template/src/lib/source.server.ts +27 -0
- package/portal-template/src/lib/source.ts +49 -0
- package/portal-template/src/lib/tabs.ts +37 -0
- package/portal-template/src/router.tsx +12 -0
- package/portal-template/src/routes/$.tsx +194 -0
- package/portal-template/src/routes/__root.tsx +56 -0
- package/portal-template/src/routes/api/search[.]json.ts +9 -0
- package/portal-template/src/routes/llms-full[.]txt.ts +10 -0
- package/portal-template/src/routes/llms[.]txt.ts +10 -0
- package/portal-template/src/routes/robots[.]txt.ts +10 -0
- package/portal-template/src/routes/sitemap[.]xml.ts +10 -0
- package/portal-template/src/routes/spa-shell.tsx +7 -0
- package/portal-template/src/routes/{$}[.]md.ts +21 -0
- package/portal-template/src/styles/app.css +33 -0
- package/portal-template/tsconfig.json +26 -0
- package/portal-template/vite.config.ts +68 -0
- package/lib/actions/plugin/record-sdk.d.ts +0 -14
- package/lib/actions/plugin/record-sdk.js +0 -60
- package/lib/actions/plugin/record-sdk.js.map +0 -1
- package/lib/actions/portal/copilot.d.ts +0 -17
- package/lib/actions/portal/copilot.js +0 -89
- package/lib/actions/portal/copilot.js.map +0 -1
- package/lib/actions/portal/quickstart.d.ts +0 -18
- package/lib/actions/portal/quickstart.js +0 -238
- package/lib/actions/portal/quickstart.js.map +0 -1
- package/lib/actions/portal/recipe/new-recipe.d.ts +0 -15
- package/lib/actions/portal/recipe/new-recipe.js +0 -177
- package/lib/actions/portal/recipe/new-recipe.js.map +0 -1
- package/lib/actions/portal/toc/new-toc.d.ts +0 -21
- package/lib/actions/portal/toc/new-toc.js +0 -95
- package/lib/actions/portal/toc/new-toc.js.map +0 -1
- package/lib/actions/sdk/merge-source-tree.d.ts +0 -12
- package/lib/actions/sdk/merge-source-tree.js +0 -78
- package/lib/actions/sdk/merge-source-tree.js.map +0 -1
- package/lib/actions/sdk/quickstart.d.ts +0 -18
- package/lib/actions/sdk/quickstart.js +0 -188
- package/lib/actions/sdk/quickstart.js.map +0 -1
- package/lib/actions/sdk/save-changes.d.ts +0 -8
- package/lib/actions/sdk/save-changes.js +0 -93
- package/lib/actions/sdk/save-changes.js.map +0 -1
- package/lib/application/portal/recipe/portal-recipe.d.ts +0 -8
- package/lib/application/portal/recipe/portal-recipe.js +0 -33
- package/lib/application/portal/recipe/portal-recipe.js.map +0 -1
- package/lib/application/portal/recipe/recipe-generator.d.ts +0 -21
- package/lib/application/portal/recipe/recipe-generator.js +0 -130
- package/lib/application/portal/recipe/recipe-generator.js.map +0 -1
- package/lib/application/portal/toc/toc-content-parser.d.ts +0 -5
- package/lib/application/portal/toc/toc-content-parser.js +0 -44
- package/lib/application/portal/toc/toc-content-parser.js.map +0 -1
- package/lib/application/portal/toc/toc-structure-generator.d.ts +0 -11
- package/lib/application/portal/toc/toc-structure-generator.js +0 -165
- package/lib/application/portal/toc/toc-structure-generator.js.map +0 -1
- package/lib/commands/portal/copilot.d.ts +0 -13
- package/lib/commands/portal/copilot.js +0 -34
- package/lib/commands/portal/copilot.js.map +0 -1
- package/lib/commands/portal/recipe/new.d.ts +0 -12
- package/lib/commands/portal/recipe/new.js +0 -45
- package/lib/commands/portal/recipe/new.js.map +0 -1
- package/lib/commands/portal/toc/new.d.ts +0 -16
- package/lib/commands/portal/toc/new.js +0 -68
- package/lib/commands/portal/toc/new.js.map +0 -1
- package/lib/commands/sdk/save-changes.d.ts +0 -14
- package/lib/commands/sdk/save-changes.js +0 -51
- package/lib/commands/sdk/save-changes.js.map +0 -1
- package/lib/infrastructure/debounce-service.d.ts +0 -10
- package/lib/infrastructure/debounce-service.js +0 -55
- package/lib/infrastructure/debounce-service.js.map +0 -1
- package/lib/infrastructure/services/portal-service.d.ts +0 -43
- package/lib/infrastructure/services/portal-service.js +0 -337
- package/lib/infrastructure/services/portal-service.js.map +0 -1
- package/lib/prompts/plugin/record-sdk.d.ts +0 -9
- package/lib/prompts/plugin/record-sdk.js +0 -40
- package/lib/prompts/plugin/record-sdk.js.map +0 -1
- package/lib/prompts/portal/copilot.d.ts +0 -18
- package/lib/prompts/portal/copilot.js +0 -82
- package/lib/prompts/portal/copilot.js.map +0 -1
- package/lib/prompts/portal/quickstart.d.ts +0 -42
- package/lib/prompts/portal/quickstart.js +0 -243
- package/lib/prompts/portal/quickstart.js.map +0 -1
- package/lib/prompts/portal/recipe/new-recipe.d.ts +0 -29
- package/lib/prompts/portal/recipe/new-recipe.js +0 -165
- package/lib/prompts/portal/recipe/new-recipe.js.map +0 -1
- package/lib/prompts/portal/toc/new-toc.d.ts +0 -16
- package/lib/prompts/portal/toc/new-toc.js +0 -50
- package/lib/prompts/portal/toc/new-toc.js.map +0 -1
- package/lib/prompts/sdk/merge-source-tree.d.ts +0 -22
- package/lib/prompts/sdk/merge-source-tree.js +0 -90
- package/lib/prompts/sdk/merge-source-tree.js.map +0 -1
- package/lib/prompts/sdk/quickstart.d.ts +0 -38
- package/lib/prompts/sdk/quickstart.js +0 -196
- package/lib/prompts/sdk/quickstart.js.map +0 -1
- package/lib/prompts/sdk/save-changes.d.ts +0 -21
- package/lib/prompts/sdk/save-changes.js +0 -84
- package/lib/prompts/sdk/save-changes.js.map +0 -1
- package/lib/types/build-context.d.ts +0 -26
- package/lib/types/build-context.js +0 -111
- package/lib/types/build-context.js.map +0 -1
- package/lib/types/events/recipe-creation-failed.d.ts +0 -5
- package/lib/types/events/recipe-creation-failed.js +0 -8
- package/lib/types/events/recipe-creation-failed.js.map +0 -1
- package/lib/types/events/sdk-changes-saved.d.ts +0 -8
- package/lib/types/events/sdk-changes-saved.js +0 -11
- package/lib/types/events/sdk-changes-saved.js.map +0 -1
- package/lib/types/events/sdk-changes-tracked.d.ts +0 -8
- package/lib/types/events/sdk-changes-tracked.js +0 -11
- package/lib/types/events/sdk-changes-tracked.js.map +0 -1
- package/lib/types/events/sdk-conflicts-resolved.d.ts +0 -8
- package/lib/types/events/sdk-conflicts-resolved.js +0 -11
- package/lib/types/events/sdk-conflicts-resolved.js.map +0 -1
- package/lib/types/events/toc-creation-failed.d.ts +0 -5
- package/lib/types/events/toc-creation-failed.js +0 -8
- package/lib/types/events/toc-creation-failed.js.map +0 -1
- package/lib/types/merge-source-tree-context.d.ts +0 -28
- package/lib/types/merge-source-tree-context.js +0 -63
- package/lib/types/merge-source-tree-context.js.map +0 -1
- package/lib/types/plugin/language-entry.d.ts +0 -9
- package/lib/types/plugin/language-entry.js +0 -64
- package/lib/types/plugin/language-entry.js.map +0 -1
- package/lib/types/recipe/recipe.d.ts +0 -22
- package/lib/types/recipe/recipe.js +0 -6
- package/lib/types/recipe/recipe.js.map +0 -1
- package/lib/types/recipe-context.d.ts +0 -9
- package/lib/types/recipe-context.js +0 -26
- package/lib/types/recipe-context.js.map +0 -1
- package/lib/types/save-changes-context.d.ts +0 -17
- package/lib/types/save-changes-context.js +0 -42
- package/lib/types/save-changes-context.js.map +0 -1
- package/lib/types/sdl/sdl.d.ts +0 -10
- package/lib/types/sdl/sdl.js +0 -18
- package/lib/types/sdl/sdl.js.map +0 -1
- package/lib/types/toc/toc-components.d.ts +0 -36
- package/lib/types/toc/toc-components.js +0 -94
- package/lib/types/toc/toc-components.js.map +0 -1
- package/lib/types/toc/toc.d.ts +0 -67
- package/lib/types/toc/toc.js +0 -2
- package/lib/types/toc/toc.js.map +0 -1
- package/lib/types/toc-context.d.ts +0 -12
- package/lib/types/toc-context.js +0 -26
- package/lib/types/toc-context.js.map +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { useOperationContext } from 'fumadocs-openapi/ui';
|
|
2
|
+
import { isJsonObject } from './json';
|
|
3
|
+
|
|
4
|
+
export type RequestExample = Pick<
|
|
5
|
+
ReturnType<typeof useOperationContext>['examples'][number],
|
|
6
|
+
'id' | 'name' | 'description'
|
|
7
|
+
>;
|
|
8
|
+
type Location = 'path' | 'query' | 'header' | 'cookie';
|
|
9
|
+
type Resolve = (node: unknown) => unknown;
|
|
10
|
+
|
|
11
|
+
interface Example {
|
|
12
|
+
summary?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Fumadocs upgrades a 3.0 document's singular `example` into an example keyed `default`.
|
|
17
|
+
const PLACEHOLDER_IDS = new Set(['_default', 'default', 'Example']);
|
|
18
|
+
|
|
19
|
+
// The order codegen-v2 consults when the request body names no example ids.
|
|
20
|
+
const NAMING_ORDER: Location[] = ['query', 'header', 'path'];
|
|
21
|
+
|
|
22
|
+
export class Parameter {
|
|
23
|
+
private constructor(
|
|
24
|
+
public readonly location: Location,
|
|
25
|
+
private readonly examples: Map<string, Example>
|
|
26
|
+
) {}
|
|
27
|
+
|
|
28
|
+
public static listIn(operation: unknown, pathItem: unknown, resolve: Resolve): Parameter[] {
|
|
29
|
+
return [...parametersOf(operation), ...parametersOf(pathItem)].flatMap(
|
|
30
|
+
(entry) => Parameter.from(resolve(entry), resolve) ?? []
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private static from(entry: unknown, resolve: Resolve): Parameter | undefined {
|
|
35
|
+
if (!isJsonObject(entry) || !isLocation(entry.in) || typeof entry.name !== 'string') {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const examples = isJsonObject(entry.examples)
|
|
39
|
+
? Object.entries(entry.examples)
|
|
40
|
+
.map(([id, example]): [string, unknown] => [id, resolve(example)])
|
|
41
|
+
.filter(isExampleEntry)
|
|
42
|
+
: [];
|
|
43
|
+
return new Parameter(entry.in, new Map(examples));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public namedExamples(): [string, Example][] {
|
|
47
|
+
return [...this.examples].filter(([id]) => !PLACEHOLDER_IDS.has(id));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function requestExamples(bodyExamples: RequestExample[], parameters: Parameter[]): RequestExample[] {
|
|
52
|
+
const named = NAMING_ORDER.flatMap((location) =>
|
|
53
|
+
parameters.filter((parameter) => parameter.location === location).map((parameter) => parameter.namedExamples())
|
|
54
|
+
).find((examples) => examples.length > 0);
|
|
55
|
+
if (bodyExamples.length > 1 || !PLACEHOLDER_IDS.has(bodyExamples[0].id) || named === undefined) {
|
|
56
|
+
return bodyExamples;
|
|
57
|
+
}
|
|
58
|
+
return named.map(([id, { summary, description }]) => ({ id, name: summary || id, description }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function parametersOf(node: unknown): unknown[] {
|
|
62
|
+
return isJsonObject(node) && Array.isArray(node.parameters) ? node.parameters : [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isLocation(value: unknown): value is Location {
|
|
66
|
+
return value === 'path' || value === 'query' || value === 'header' || value === 'cookie';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isExampleEntry(entry: [string, unknown]): entry is [string, Example] {
|
|
70
|
+
return isJsonObject(entry[1]) && 'value' in entry[1];
|
|
71
|
+
}
|
|
72
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { portal } from './portal';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Absolute URL of a page, or null when the portal has no configured address.
|
|
5
|
+
* Canonical links and the sitemap are both omitted in that case rather than
|
|
6
|
+
* guessed, since a wrong canonical is worse than none.
|
|
7
|
+
*/
|
|
8
|
+
export function absoluteUrl(pageUrl: string): string | null {
|
|
9
|
+
if (!portal.siteUrl) return null;
|
|
10
|
+
return portal.siteUrl + pageUrl;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function canonicalLink(pageUrl: string): { rel: string; href: string }[] {
|
|
14
|
+
const href = absoluteUrl(pageUrl);
|
|
15
|
+
return href === null ? [] : [{ rel: 'canonical', href }];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function renderRobots(): string {
|
|
19
|
+
const sitemap = absoluteUrl('/sitemap.xml');
|
|
20
|
+
return ['User-agent: *', 'Allow: /', ...(sitemap === null ? [] : ['', `Sitemap: ${sitemap}`])].join('\n') + '\n';
|
|
21
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type * as PageTree from 'fumadocs-core/page-tree';
|
|
2
|
+
import { createGetUrl } from 'fumadocs-core/source';
|
|
3
|
+
|
|
4
|
+
export const docsRoute = '/';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Where the reference pages of every specification are mounted, one folder per section
|
|
8
|
+
* beneath it. Shared so the navigation transformer positions the same folder the OpenAPI
|
|
9
|
+
* sections are written into.
|
|
10
|
+
*/
|
|
11
|
+
export const apiBaseDir = 'api';
|
|
12
|
+
|
|
13
|
+
const getDocsUrl = createGetUrl(docsRoute);
|
|
14
|
+
|
|
15
|
+
/** Whether a page at `url` sits among these nodes, at any depth. */
|
|
16
|
+
export function containsUrl(nodes: PageTree.Node[], url: string): boolean {
|
|
17
|
+
return nodes.some((node) => {
|
|
18
|
+
if (node.type === 'page') {
|
|
19
|
+
return node.url === url;
|
|
20
|
+
}
|
|
21
|
+
return node.type === 'folder' && (node.index?.url === url || containsUrl(node.children, url));
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getPageMarkdownUrl(page: { slugs: string[]; locale?: string }) {
|
|
26
|
+
const segments = [...page.slugs];
|
|
27
|
+
if (segments.length === 0) {
|
|
28
|
+
segments.push('index.md');
|
|
29
|
+
} else {
|
|
30
|
+
segments[segments.length - 1] += '.md';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { segments, url: getDocsUrl(segments, page.locale) };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function slugsFromSplat(splat: string | undefined): string[] {
|
|
37
|
+
return (splat ?? '')
|
|
38
|
+
.split('/')
|
|
39
|
+
.filter((segment) => segment.length > 0)
|
|
40
|
+
.map(encodeURI);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @returns page slugs */
|
|
44
|
+
export function decodeMarkdownUrl(segments: string[]) {
|
|
45
|
+
if (segments.length === 0) return [];
|
|
46
|
+
|
|
47
|
+
const out = [...segments];
|
|
48
|
+
out[out.length - 1] = (out.at(-1) ?? '').replace(/\.md$/, '');
|
|
49
|
+
if (out.length === 1 && out[0] === 'index') out.pop();
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createBundledHighlighter } from 'shiki/core';
|
|
2
|
+
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
|
|
3
|
+
|
|
4
|
+
// Re-exported untouched: Fumadocs imports it from the `shiki` entry point this file stands
|
|
5
|
+
// in for, though the bundle itself builds its highlighter on the JavaScript engine.
|
|
6
|
+
export { createOnigurumaEngine } from 'shiki/engine/oniguruma';
|
|
7
|
+
|
|
8
|
+
type LanguageImport = () => Promise<unknown>;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Stands in for the `shiki` entry point Fumadocs imports to build its highlighter (see the
|
|
12
|
+
* alias in `vite.config.ts`). That entry carries Shiki's whole catalogue as dynamic imports,
|
|
13
|
+
* so the bundler emits a chunk per grammar and a one-endpoint portal ships some ten megabytes
|
|
14
|
+
* of them for languages nothing on the site is written in. Only what a generated portal can
|
|
15
|
+
* contain is bundled; Fumadocs falls back to plain text for anything outside this map, so an
|
|
16
|
+
* unlisted language renders unhighlighted rather than broken.
|
|
17
|
+
*/
|
|
18
|
+
const languages = {
|
|
19
|
+
// The seven the CLI generates SDKs for (src/types/sdk/generate.ts).
|
|
20
|
+
csharp: () => import('shiki/dist/langs/csharp.mjs'),
|
|
21
|
+
go: () => import('shiki/dist/langs/go.mjs'),
|
|
22
|
+
java: () => import('shiki/dist/langs/java.mjs'),
|
|
23
|
+
php: () => import('shiki/dist/langs/php.mjs'),
|
|
24
|
+
python: () => import('shiki/dist/langs/python.mjs'),
|
|
25
|
+
ruby: () => import('shiki/dist/langs/ruby.mjs'),
|
|
26
|
+
typescript: () => import('shiki/dist/langs/typescript.mjs'),
|
|
27
|
+
|
|
28
|
+
// Shell commands, and the shapes a response or a specification is shown in.
|
|
29
|
+
http: () => import('shiki/dist/langs/http.mjs'),
|
|
30
|
+
json: () => import('shiki/dist/langs/json.mjs'),
|
|
31
|
+
jsonc: () => import('shiki/dist/langs/jsonc.mjs'),
|
|
32
|
+
shellscript: () => import('shiki/dist/langs/shellscript.mjs'),
|
|
33
|
+
shellsession: () => import('shiki/dist/langs/shellsession.mjs'),
|
|
34
|
+
xml: () => import('shiki/dist/langs/xml.mjs'),
|
|
35
|
+
yaml: () => import('shiki/dist/langs/yaml.mjs'),
|
|
36
|
+
|
|
37
|
+
// What the Markdown pages beside the reference are written in.
|
|
38
|
+
css: () => import('shiki/dist/langs/css.mjs'),
|
|
39
|
+
diff: () => import('shiki/dist/langs/diff.mjs'),
|
|
40
|
+
graphql: () => import('shiki/dist/langs/graphql.mjs'),
|
|
41
|
+
html: () => import('shiki/dist/langs/html.mjs'),
|
|
42
|
+
javascript: () => import('shiki/dist/langs/javascript.mjs'),
|
|
43
|
+
jsx: () => import('shiki/dist/langs/jsx.mjs'),
|
|
44
|
+
markdown: () => import('shiki/dist/langs/markdown.mjs'),
|
|
45
|
+
sql: () => import('shiki/dist/langs/sql.mjs'),
|
|
46
|
+
tsx: () => import('shiki/dist/langs/tsx.mjs')
|
|
47
|
+
} satisfies Record<string, LanguageImport>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Shiki's own bundle resolves `ts` or `yml` through an alias table beside its grammars; a
|
|
51
|
+
* hand-built map has none, so an alias reaches Fumadocs as an unknown language and is replaced
|
|
52
|
+
* with `text`. Each shares its grammar's import, as Shiki's `bundledLanguagesAlias` does, so
|
|
53
|
+
* the bundler still emits one chunk per language rather than one per spelling. Taken from
|
|
54
|
+
* Shiki's `bundledLanguagesInfo`; `test/portal-template.test.ts` holds them to it.
|
|
55
|
+
*/
|
|
56
|
+
const aliases: Record<string, keyof typeof languages> = {
|
|
57
|
+
'c#': 'csharp',
|
|
58
|
+
cs: 'csharp',
|
|
59
|
+
py: 'python',
|
|
60
|
+
rb: 'ruby',
|
|
61
|
+
ts: 'typescript',
|
|
62
|
+
cts: 'typescript',
|
|
63
|
+
mts: 'typescript',
|
|
64
|
+
js: 'javascript',
|
|
65
|
+
cjs: 'javascript',
|
|
66
|
+
mjs: 'javascript',
|
|
67
|
+
bash: 'shellscript',
|
|
68
|
+
sh: 'shellscript',
|
|
69
|
+
shell: 'shellscript',
|
|
70
|
+
zsh: 'shellscript',
|
|
71
|
+
console: 'shellsession',
|
|
72
|
+
yml: 'yaml',
|
|
73
|
+
md: 'markdown',
|
|
74
|
+
gql: 'graphql'
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type BundledLanguage = keyof typeof languages;
|
|
78
|
+
|
|
79
|
+
/** The grammar a fence's language names, by its own name or an alias; null for one not bundled. */
|
|
80
|
+
export function bundledLanguage(name: string): BundledLanguage | null {
|
|
81
|
+
if (Object.hasOwn(languages, name)) {
|
|
82
|
+
return name as BundledLanguage;
|
|
83
|
+
}
|
|
84
|
+
return Object.hasOwn(aliases, name) ? aliases[name] : null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const bundledLanguages = {
|
|
88
|
+
...languages,
|
|
89
|
+
...Object.fromEntries(Object.entries(aliases).map(([alias, id]) => [alias, languages[id]]))
|
|
90
|
+
} as never;
|
|
91
|
+
|
|
92
|
+
/** The two Fumadocs asks for by default; the rest of Shiki's themes are never requested. */
|
|
93
|
+
const bundledThemes = {
|
|
94
|
+
'github-light': () => import('shiki/dist/themes/github-light.mjs'),
|
|
95
|
+
'github-dark': () => import('shiki/dist/themes/github-dark.mjs')
|
|
96
|
+
} as never;
|
|
97
|
+
|
|
98
|
+
export const createHighlighter = createBundledHighlighter({
|
|
99
|
+
langs: bundledLanguages,
|
|
100
|
+
themes: bundledThemes,
|
|
101
|
+
engine: () => createJavaScriptRegexEngine()
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export { createJavaScriptRegexEngine };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { absoluteUrl } from './seo';
|
|
2
|
+
import { source } from './source.server';
|
|
3
|
+
|
|
4
|
+
export function renderSitemap(): string {
|
|
5
|
+
const urls = ['/', ...source.getPages().map((page) => page.url)];
|
|
6
|
+
const entries = [...new Set(urls)]
|
|
7
|
+
.map((url) => ` <url>\n <loc>${escapeXml(absoluteUrl(url) ?? url)}</loc>\n </url>`)
|
|
8
|
+
.join('\n');
|
|
9
|
+
|
|
10
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${entries}\n</urlset>\n`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function escapeXml(value: string): string {
|
|
14
|
+
return value
|
|
15
|
+
.replaceAll('&', '&')
|
|
16
|
+
.replaceAll('<', '<')
|
|
17
|
+
.replaceAll('>', '>')
|
|
18
|
+
.replaceAll('"', '"')
|
|
19
|
+
.replaceAll("'", ''');
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { loader } from 'fumadocs-core/source';
|
|
2
|
+
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
|
|
3
|
+
import { openapiPlugin } from 'fumadocs-openapi/server';
|
|
4
|
+
import { docsRoute } from './shared';
|
|
5
|
+
import { docs, generated } from './source';
|
|
6
|
+
import { GENERATED_SOURCE, navigationTransformer, OPENAPI_SOURCE, tabsTransformer } from './navigation';
|
|
7
|
+
import { openApiSource } from './openapi.server';
|
|
8
|
+
|
|
9
|
+
// Reads every OpenAPI document off disk, so this only runs at build time, inside server
|
|
10
|
+
// functions and server route handlers. Importing it from client code fails the build.
|
|
11
|
+
// The generated and reference pages go in under the keys the transformer tells them apart by.
|
|
12
|
+
export const source = loader(
|
|
13
|
+
{
|
|
14
|
+
docs: docs.toFumadocsSource(),
|
|
15
|
+
[GENERATED_SOURCE]: generated.toFumadocsSource(),
|
|
16
|
+
[OPENAPI_SOURCE]: await openApiSource()
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
baseUrl: docsRoute,
|
|
20
|
+
plugins: [lucideIconsPlugin(), openapiPlugin()],
|
|
21
|
+
// No fallback tree: it is built from the files that became no node, and `nav.json` never
|
|
22
|
+
// does, so every build would otherwise grow a second tree that nothing renders and that
|
|
23
|
+
// the sidebar payload carries to every visitor. The tabs are formed from the root once it
|
|
24
|
+
// is ordered, which is why their transformer comes second.
|
|
25
|
+
pageTree: { transformers: [navigationTransformer(), tabsTransformer()], generateFallback: false }
|
|
26
|
+
}
|
|
27
|
+
);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defineDocs } from 'fumadocs-mdx/macro';
|
|
2
|
+
import { applyMdxPreset } from 'fumadocs-mdx/config';
|
|
3
|
+
import { rehypeCodeDefaultOptions } from 'fumadocs-core/mdx-plugins';
|
|
4
|
+
import rehypeRaw from 'rehype-raw';
|
|
5
|
+
import { rehypeCodeTitles, rehypeKeepCodeMeta } from './rehype-code-titles';
|
|
6
|
+
|
|
7
|
+
// What `rehype-raw` must hand on untouched, being MDX's own nodes rather than HTML.
|
|
8
|
+
const MDX_NODE_TYPES = ['mdxFlowExpression', 'mdxJsxFlowElement', 'mdxJsxTextElement', 'mdxTextExpression', 'mdxjsEsm'];
|
|
9
|
+
|
|
10
|
+
// The CLI copies the source's pages here. Relative, because the macro embeds the literal in the
|
|
11
|
+
// browser bundle, and an absolute one would publish the build machine's directories.
|
|
12
|
+
//
|
|
13
|
+
// This module is imported by the browser bundle, so it must stay free of anything that touches
|
|
14
|
+
// the filesystem. The loader that reads the OpenAPI documents lives in `source.server.ts`.
|
|
15
|
+
export const docs = defineDocs({
|
|
16
|
+
dir: 'content',
|
|
17
|
+
docs: { async: true, postprocess: { includeProcessedMarkdown: true } },
|
|
18
|
+
// Restricted to our own file, replacing the default of every .json and .yaml in the
|
|
19
|
+
// content directory. Without it a leftover `meta.json` is loaded as a folder's metadata
|
|
20
|
+
// and applied before the transformer runs -- and since a metadata file hides whatever it
|
|
21
|
+
// does not name, the transformer could not put those pages back.
|
|
22
|
+
meta: { files: ['**/nav.json'] }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// The pages the CLI writes into this project, resolved against the Vite root like `content`.
|
|
26
|
+
export const generated = defineDocs({
|
|
27
|
+
dir: 'generated',
|
|
28
|
+
docs: {
|
|
29
|
+
async: true,
|
|
30
|
+
// Its components give their own Markdown, where a string would keep them as JSX tags.
|
|
31
|
+
postprocess: { includeProcessedMarkdown: { output: 'function' } },
|
|
32
|
+
// Options given here replace Fumadocs' defaults, hence the preset.
|
|
33
|
+
mdxOptions: applyMdxPreset({
|
|
34
|
+
// A remote image is never fetched for its size, which would make the build depend on its host.
|
|
35
|
+
remarkImageOptions: { external: false },
|
|
36
|
+
// The SDK pages' design heads a block with its title alone, without Fumadocs' language icon.
|
|
37
|
+
rehypeCodeOptions: { ...rehypeCodeDefaultOptions, icon: false },
|
|
38
|
+
// The SDK docs' HTML fails the build unrendered; not sanitized, as it comes from the owner's own spec.
|
|
39
|
+
// The titles go in after it, and ahead of `rehypeCode`, the first of the defaults, which reads them.
|
|
40
|
+
rehypePlugins: (defaults) => [
|
|
41
|
+
rehypeKeepCodeMeta,
|
|
42
|
+
[rehypeRaw, { passThrough: MDX_NODE_TYPES }],
|
|
43
|
+
rehypeCodeTitles,
|
|
44
|
+
...defaults
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
},
|
|
48
|
+
meta: { files: ['**/nav.json'] }
|
|
49
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type * as PageTree from 'fumadocs-core/page-tree';
|
|
2
|
+
import type { LayoutTab } from 'fumadocs-ui/layouts/shared';
|
|
3
|
+
import { containsUrl, docsRoute } from './shared';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One tab per root folder at the top of the tree, which is every top-level node once the tabs
|
|
7
|
+
* transformer has run. Given to the layout rather than left to Fumadocs, which links a tab to
|
|
8
|
+
* its folder's first direct page and so leaves out a tab holding only folders -- as the API
|
|
9
|
+
* reference does whenever its operations are grouped. Each stays bound to its folder, which is
|
|
10
|
+
* how the active tab is found.
|
|
11
|
+
*/
|
|
12
|
+
export function portalTabs(tree: PageTree.Root): LayoutTab[] {
|
|
13
|
+
return tree.children.flatMap((node) => {
|
|
14
|
+
if (node.type !== 'folder' || node.root !== true) return [];
|
|
15
|
+
// Home keeps the order the root nav.json gives, which need not put the home page first.
|
|
16
|
+
const url = containsUrl([node], docsRoute) ? docsRoute : firstPageUrl(node);
|
|
17
|
+
return url === undefined
|
|
18
|
+
? []
|
|
19
|
+
: [{ title: node.name, description: node.description, icon: node.icon, url, $folder: node }];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Depth first, as the sidebar lists them, so the tab opens on the page at its top. A link
|
|
25
|
+
* that leaves the portal is passed over, as Fumadocs passes it over for a folder's own link.
|
|
26
|
+
*/
|
|
27
|
+
function firstPageUrl(folder: PageTree.Folder): string | undefined {
|
|
28
|
+
if (folder.index !== undefined) return folder.index.url;
|
|
29
|
+
for (const child of folder.children) {
|
|
30
|
+
if (child.type === 'page' && !child.external) return child.url;
|
|
31
|
+
if (child.type === 'folder') {
|
|
32
|
+
const url = firstPageUrl(child);
|
|
33
|
+
if (url !== undefined) return url;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
|
|
2
|
+
import { routeTree } from './routeTree.gen';
|
|
3
|
+
import { NotFound } from '@/components/not-found';
|
|
4
|
+
|
|
5
|
+
export function getRouter() {
|
|
6
|
+
return createTanStackRouter({
|
|
7
|
+
routeTree,
|
|
8
|
+
defaultPreload: 'intent',
|
|
9
|
+
scrollRestoration: true,
|
|
10
|
+
defaultNotFoundComponent: NotFound
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { createFileRoute, getRouteApi, isNotFound, isRedirect, notFound } from '@tanstack/react-router';
|
|
2
|
+
import { createServerFn } from '@tanstack/react-start';
|
|
3
|
+
import { docs, generated } from '@/lib/source';
|
|
4
|
+
import { source } from '@/lib/source.server';
|
|
5
|
+
import { PortalLayout } from '@/lib/layout';
|
|
6
|
+
import { getPageMarkdownUrl, slugsFromSplat } from '@/lib/shared';
|
|
7
|
+
import { portal } from '@/lib/portal';
|
|
8
|
+
import { absoluteUrl, canonicalLink } from '@/lib/seo';
|
|
9
|
+
import { useFumadocsLoader } from 'fumadocs-core/source/client';
|
|
10
|
+
import { usePathname } from 'fumadocs-core/framework';
|
|
11
|
+
import {
|
|
12
|
+
DocsBody,
|
|
13
|
+
DocsDescription,
|
|
14
|
+
DocsPage,
|
|
15
|
+
DocsTitle,
|
|
16
|
+
MarkdownCopyButton,
|
|
17
|
+
ViewOptionsPopover
|
|
18
|
+
} from 'fumadocs-ui/layouts/notebook/page';
|
|
19
|
+
import { staticFunctionMiddleware } from '@tanstack/start-static-server-functions';
|
|
20
|
+
import { Suspense, use, type ReactNode } from 'react';
|
|
21
|
+
import { useMDXComponents } from '@/components/mdx';
|
|
22
|
+
import { OpenAPIPage } from '@/components/api-page';
|
|
23
|
+
import { slimOpenAPIPageProps } from '@/lib/openapi-slim';
|
|
24
|
+
|
|
25
|
+
const rootRoute = getRouteApi('__root__');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The collections a Markdown page is compiled into, by the loader source it came from. A
|
|
29
|
+
* page's `path` is relative to its own collection's directory, so it is looked up there.
|
|
30
|
+
*/
|
|
31
|
+
const collections = { docs, generated };
|
|
32
|
+
|
|
33
|
+
export const Route = createFileRoute('/$')({
|
|
34
|
+
component: Page,
|
|
35
|
+
loader: async ({ params }) => {
|
|
36
|
+
const slugs = slugsFromSplat(params._splat);
|
|
37
|
+
const data = await loadPage(slugs);
|
|
38
|
+
|
|
39
|
+
if (data.type === 'docs') {
|
|
40
|
+
await collections[data.collection].getPage(data.path)?.preload();
|
|
41
|
+
}
|
|
42
|
+
return data;
|
|
43
|
+
},
|
|
44
|
+
head: ({ loaderData, params }) => {
|
|
45
|
+
const title = loaderData && loaderData.type !== 'home' ? `${loaderData.title} | ${portal.name}` : portal.name;
|
|
46
|
+
const description = loaderData?.description ?? portal.description;
|
|
47
|
+
const pageUrl = `/${slugsFromSplat(params._splat).join('/')}`;
|
|
48
|
+
const absolute = absoluteUrl(pageUrl);
|
|
49
|
+
return {
|
|
50
|
+
// Without the og:* pair, a documentation link pasted into Slack, Teams or LinkedIn
|
|
51
|
+
// unfurls as a bare URL.
|
|
52
|
+
meta: [
|
|
53
|
+
{ title },
|
|
54
|
+
...(description ? [{ name: 'description', content: description }] : []),
|
|
55
|
+
{ property: 'og:title', content: title },
|
|
56
|
+
...(description ? [{ property: 'og:description', content: description }] : []),
|
|
57
|
+
{ property: 'og:type', content: 'website' },
|
|
58
|
+
{ property: 'og:site_name', content: portal.name },
|
|
59
|
+
...(absolute ? [{ property: 'og:url', content: absolute }] : []),
|
|
60
|
+
{ name: 'twitter:card', content: 'summary' }
|
|
61
|
+
],
|
|
62
|
+
links: canonicalLink(pageUrl)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const serverLoader = createServerFn({
|
|
68
|
+
method: 'GET'
|
|
69
|
+
})
|
|
70
|
+
.validator((slugs: string[]) => slugs)
|
|
71
|
+
.middleware([staticFunctionMiddleware])
|
|
72
|
+
.handler(async ({ data: slugs }) => {
|
|
73
|
+
const page = source.getPage(slugs);
|
|
74
|
+
|
|
75
|
+
if (!page) {
|
|
76
|
+
// A project without content/index.md(x) still gets a landing page.
|
|
77
|
+
if (slugs.length === 0) {
|
|
78
|
+
return { type: 'home' as const, title: portal.name, description: portal.description };
|
|
79
|
+
}
|
|
80
|
+
throw notFound();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (page.type === 'openapi') {
|
|
84
|
+
return {
|
|
85
|
+
type: 'openapi' as const,
|
|
86
|
+
title: page.data.title,
|
|
87
|
+
description: page.data.description ?? null,
|
|
88
|
+
props: slimOpenAPIPageProps(page.data.getOpenAPIPageProps())
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
type: 'docs' as const,
|
|
94
|
+
collection: page.type,
|
|
95
|
+
title: page.data.title,
|
|
96
|
+
description: page.data.description ?? null,
|
|
97
|
+
path: page.path,
|
|
98
|
+
markdownUrl: getPageMarkdownUrl(page).url
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// The condition `staticFunctionMiddleware` itself uses to answer from the prerendered cache
|
|
103
|
+
// instead of calling the handler.
|
|
104
|
+
const answeredFromStaticCache = process.env.NODE_ENV === 'production' && typeof document !== 'undefined';
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* An unknown URL has no prerendered response, and the middleware fetches one without checking
|
|
108
|
+
* the status, so `.json()` throws on whatever the host returns for a missing file and the
|
|
109
|
+
* error boundary renders in place of the not-found page. Only the cache path is rewritten,
|
|
110
|
+
* where a failed fetch can only mean the page does not exist; everywhere else -- the prerender
|
|
111
|
+
* pass, `portal serve` -- a real failure still surfaces.
|
|
112
|
+
*/
|
|
113
|
+
async function loadPage(slugs: string[]) {
|
|
114
|
+
try {
|
|
115
|
+
return await serverLoader({ data: slugs });
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (!answeredFromStaticCache || isNotFound(error) || isRedirect(error)) throw error;
|
|
118
|
+
// A missing page is the ordinary reason to land here, but a network failure or a host
|
|
119
|
+
// answering with its own error page fails the same way, so the cause is named rather
|
|
120
|
+
// than assumed.
|
|
121
|
+
console.error('Falling back to the not-found page; loading this page failed with:', error);
|
|
122
|
+
throw notFound();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function Content({
|
|
127
|
+
collection,
|
|
128
|
+
path,
|
|
129
|
+
markdownUrl
|
|
130
|
+
}: Readonly<{ collection: keyof typeof collections; path: string; markdownUrl: string }>) {
|
|
131
|
+
const page = collections[collection].getPage(path);
|
|
132
|
+
if (!page) throw new Error(`unknown page: ${path}`);
|
|
133
|
+
|
|
134
|
+
const { toc } = use(page.load());
|
|
135
|
+
const PageBody = page.body;
|
|
136
|
+
const pathname = usePathname();
|
|
137
|
+
// Named, or the popover reads `window.location.href` and sends the reader's query and hash on.
|
|
138
|
+
const pageUrl = typeof window === 'undefined' ? pathname : new URL(pathname, window.location.origin).toString();
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<DocsPage toc={toc} full={page.full}>
|
|
142
|
+
<DocsTitle>{page.title}</DocsTitle>
|
|
143
|
+
<DocsDescription>{page.description}</DocsDescription>
|
|
144
|
+
<div className="flex flex-row gap-2 items-center border-b -mt-4 pb-6">
|
|
145
|
+
<MarkdownCopyButton markdownUrl={markdownUrl} />
|
|
146
|
+
{/* Sends the reader to an external AI vendor, so a portal published under someone
|
|
147
|
+
else's brand can turn it off. */}
|
|
148
|
+
{portal.pageActions ? <ViewOptionsPopover markdownUrl={markdownUrl} pageUrl={pageUrl} /> : null}
|
|
149
|
+
</div>
|
|
150
|
+
<DocsBody>
|
|
151
|
+
<PageBody components={useMDXComponents()} />
|
|
152
|
+
</DocsBody>
|
|
153
|
+
</DocsPage>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function Home({ title, description }: Readonly<{ title: string; description: string | null }>) {
|
|
158
|
+
return (
|
|
159
|
+
<DocsPage>
|
|
160
|
+
<DocsTitle>{title}</DocsTitle>
|
|
161
|
+
{description ? <DocsDescription>{description}</DocsDescription> : null}
|
|
162
|
+
<DocsBody>
|
|
163
|
+
<p>Use the navigation to browse the API reference and guides.</p>
|
|
164
|
+
</DocsBody>
|
|
165
|
+
</DocsPage>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function Page() {
|
|
170
|
+
const page = useFumadocsLoader(Route.useLoaderData());
|
|
171
|
+
const { pageTree } = useFumadocsLoader(rootRoute.useLoaderData());
|
|
172
|
+
let content: ReactNode;
|
|
173
|
+
|
|
174
|
+
if (page.type === 'home') {
|
|
175
|
+
content = <Home title={page.title} description={page.description} />;
|
|
176
|
+
} else if (page.type === 'openapi') {
|
|
177
|
+
content = (
|
|
178
|
+
<DocsPage full>
|
|
179
|
+
<DocsTitle>{page.title}</DocsTitle>
|
|
180
|
+
<DocsBody>
|
|
181
|
+
<OpenAPIPage {...page.props} />
|
|
182
|
+
</DocsBody>
|
|
183
|
+
</DocsPage>
|
|
184
|
+
);
|
|
185
|
+
} else {
|
|
186
|
+
content = (
|
|
187
|
+
<Suspense>
|
|
188
|
+
<Content collection={page.collection} path={page.path} markdownUrl={page.markdownUrl} />
|
|
189
|
+
</Suspense>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return <PortalLayout tree={pageTree}>{content}</PortalLayout>;
|
|
194
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createRootRoute, HeadContent, Outlet, Scripts } from '@tanstack/react-router';
|
|
2
|
+
import { createServerFn } from '@tanstack/react-start';
|
|
3
|
+
import { staticFunctionMiddleware } from '@tanstack/start-static-server-functions';
|
|
4
|
+
import { source } from '@/lib/source.server';
|
|
5
|
+
import appCss from '@/styles/app.css?url';
|
|
6
|
+
import { RootProvider } from 'fumadocs-ui/provider/tanstack';
|
|
7
|
+
import SearchDialog from '@/components/search';
|
|
8
|
+
import { portal } from '@/lib/portal';
|
|
9
|
+
|
|
10
|
+
// The sidebar tree is the same on every page. Loaded here, once, it is written to a single
|
|
11
|
+
// cache file instead of being repeated in every page's own loader payload.
|
|
12
|
+
const loadPageTree = createServerFn({ method: 'GET' })
|
|
13
|
+
.middleware([staticFunctionMiddleware])
|
|
14
|
+
.handler(async () => ({ pageTree: await source.serializePageTree(source.getPageTree()) }));
|
|
15
|
+
|
|
16
|
+
// Without one the browser tab shows the blank-document icon on every page.
|
|
17
|
+
const iconLinks = portal.favicon
|
|
18
|
+
? [{ rel: 'icon', href: portal.favicon.url, ...(portal.favicon.type ? { type: portal.favicon.type } : {}) }]
|
|
19
|
+
: [];
|
|
20
|
+
|
|
21
|
+
// A portal fixed to one mode keeps to it whatever the visitor's system prefers, and offers no
|
|
22
|
+
// way out: the layout hides the switch, and the `D` hotkey is turned off here.
|
|
23
|
+
const theme =
|
|
24
|
+
portal.colorMode === 'both'
|
|
25
|
+
? undefined
|
|
26
|
+
: { forcedTheme: portal.colorMode, defaultTheme: portal.colorMode, enableSystem: false, hotKey: false as const };
|
|
27
|
+
|
|
28
|
+
export const Route = createRootRoute({
|
|
29
|
+
loader: () => loadPageTree(),
|
|
30
|
+
head: () => ({
|
|
31
|
+
meta: [
|
|
32
|
+
{ charSet: 'utf-8' },
|
|
33
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
34
|
+
{ title: portal.name },
|
|
35
|
+
...(portal.description ? [{ name: 'description', content: portal.description }] : [])
|
|
36
|
+
],
|
|
37
|
+
links: [{ rel: 'stylesheet', href: appCss }, ...iconLinks]
|
|
38
|
+
}),
|
|
39
|
+
component: RootComponent
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
function RootComponent() {
|
|
43
|
+
return (
|
|
44
|
+
<html lang="en" suppressHydrationWarning>
|
|
45
|
+
<head>
|
|
46
|
+
<HeadContent />
|
|
47
|
+
</head>
|
|
48
|
+
<body className="flex flex-col min-h-screen">
|
|
49
|
+
<RootProvider search={{ SearchDialog }} theme={theme}>
|
|
50
|
+
<Outlet />
|
|
51
|
+
</RootProvider>
|
|
52
|
+
<Scripts />
|
|
53
|
+
</body>
|
|
54
|
+
</html>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
+
import { source } from '@/lib/source.server';
|
|
3
|
+
import { createFromSource } from 'fumadocs-core/search/server';
|
|
4
|
+
|
|
5
|
+
const server = createFromSource(source, { language: 'english' });
|
|
6
|
+
|
|
7
|
+
export const Route = createFileRoute('/api/search.json')({
|
|
8
|
+
server: { handlers: { GET: () => server.staticGET() } }
|
|
9
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
+
import { renderFull } from '@/lib/llms.server';
|
|
3
|
+
|
|
4
|
+
export const Route = createFileRoute('/llms-full.txt')({
|
|
5
|
+
server: {
|
|
6
|
+
handlers: {
|
|
7
|
+
GET: async () => new Response(await renderFull())
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
});
|