@eventcatalog/core 5.0.0-beta.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -12
- package/README.md +5 -5
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +91 -44
- package/dist/analytics/log-build.d.cts +2 -2
- package/dist/analytics/log-build.d.ts +2 -2
- package/dist/analytics/log-build.js +6 -5
- package/dist/analytics/studio-usage.cjs +90 -0
- package/dist/analytics/studio-usage.d.cts +5 -0
- package/dist/analytics/studio-usage.d.ts +5 -0
- package/dist/analytics/studio-usage.js +10 -0
- package/dist/catalog-runtime.cjs +1 -1
- package/dist/{chunk-RFIXKATC.js → chunk-4G7FSRPN.js} +35 -42
- package/dist/{chunk-AWOO63ME.js → chunk-AD7CL772.js} +11 -4
- package/dist/chunk-CA6WCQ2T.js +54 -0
- package/dist/{chunk-GAHKCOQM.js → chunk-JZN4RSMF.js} +1 -1
- package/dist/{chunk-JQMYHZWI.js → chunk-NEAVAFSJ.js} +16 -8
- package/dist/{chunk-4CFZUHGG.js → chunk-NIVST4WY.js} +1 -1
- package/dist/{chunk-ENAG6UH7.js → chunk-NKNOXQ62.js} +1 -6
- package/dist/{chunk-ZEY2XUJN.js → chunk-OX6TSVHY.js} +6 -6
- package/dist/{chunk-36RYTYT5.js → chunk-PD7KTSYN.js} +1 -1
- package/dist/{chunk-EUNQJO3J.js → chunk-RE7UTPWH.js} +1 -1
- package/dist/chunk-S5GWAUG5.js +29 -0
- package/dist/{chunk-TZVDMWQX.js → chunk-YQGRMDRB.js} +4 -2
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/docs/api/02-config.md +57 -7
- package/dist/docs/development/00-why-eventcatalog.md +11 -11
- package/dist/docs/development/01-fundamentals.md +20 -13
- package/dist/docs/development/01-getting-started/configuration-overview.md +2 -2
- package/dist/docs/development/01-getting-started/installation.md +9 -1
- package/dist/docs/development/_getting-started.mdx +1 -1
- package/dist/docs/development/ask-your-architecture/01-intro.md +5 -5
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/01-what-is-eventcatalog-assistant.md +0 -4
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/02-configuration.md +15 -3
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/03-bring-your-own-tools.md +0 -3
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/_category_.json +1 -1
- package/dist/docs/development/ask-your-architecture/02-llms.txt.md +1 -1
- package/dist/docs/development/ask-your-architecture/{05-skills/01-introduction.md → 03-install-skills.md} +57 -7
- package/dist/docs/development/ask-your-architecture/03-mcp-server/_category_.json +1 -1
- package/dist/docs/development/ask-your-architecture/03-mcp-server/getting-started.md +86 -33
- package/dist/docs/development/ask-your-architecture/03-mcp-server/introduction.md +14 -4
- package/dist/docs/development/ask-your-architecture/03-schemas.txt.md +1 -1
- package/dist/docs/development/ask-your-architecture/04-agents/_category_.json +1 -1
- package/dist/docs/development/authentication/01-introduction.md +2 -23
- package/dist/docs/development/authentication/02-enabling-authentication.md +0 -20
- package/dist/docs/development/authentication/07-rbac-middleware.md +0 -2
- package/dist/docs/development/authentication/providers/03-setting-up-github.md +0 -2
- package/dist/docs/development/authentication/providers/03a-setting-up-google.md +0 -2
- package/dist/docs/development/authentication/providers/04-setting-up-azure-ad.md +0 -2
- package/dist/docs/development/authentication/providers/05-setting-up-okta.md +0 -3
- package/dist/docs/development/authentication/providers/06-setting-up-auth0.md +0 -2
- package/dist/docs/development/bring-your-own-documentation/01-introduction.md +0 -4
- package/dist/docs/development/bring-your-own-documentation/custom-pages/01-introduction.md +0 -3
- package/dist/docs/development/bring-your-own-documentation/custom-pages/02-adding-custom-docs.md +0 -17
- package/dist/docs/development/bring-your-own-documentation/custom-pages/03-components.md +0 -4
- package/dist/docs/development/bring-your-own-documentation/custom-pages/04-owners.md +0 -2
- package/dist/docs/development/bring-your-own-documentation/resource-docs/01-introduction.md +1 -3
- package/dist/docs/development/bring-your-own-documentation/resource-docs/02-adding-resource-docs.md +1 -4
- package/dist/docs/development/bring-your-own-documentation/resource-docs/03-categories.md +0 -2
- package/dist/docs/development/bring-your-own-documentation/resource-docs/04-versioning.md +1 -3
- package/dist/docs/development/components/components/11-flow.md +17 -0
- package/dist/docs/development/components/components/15-nodegraph.md +43 -10
- package/dist/docs/development/components/components/18-remote-schema.md +1 -4
- package/dist/docs/development/components/custom-components/07-reference.md +14 -0
- package/dist/docs/development/customization/02-themes.md +0 -5
- package/dist/docs/development/customization/03-search.md +1 -1
- package/dist/docs/development/customization/05-custom-pages-and-api-routes/01-introduction.md +0 -2
- package/dist/docs/development/customization/05-custom-pages-and-api-routes/04-reference.md +7 -1
- package/dist/docs/development/customization/05-resource-sidebar.md +1 -1
- package/dist/docs/development/customization/09-embed-eventcatalog.md +20 -25
- package/dist/docs/development/deployment/hosting-options.md +7 -2
- package/dist/docs/development/developer-tools/eventcatalog-linter/how-to/05-fix-common-problems.md +16 -0
- package/dist/docs/development/developer-tools/eventcatalog-linter/reference/03-rules.md +31 -1
- package/dist/docs/development/developer-tools/eventcatalog-linter/reference/05-supported-resources.md +1 -1
- package/dist/docs/development/governance/architecture-change-detection/01-introduction.md +0 -10
- package/dist/docs/development/governance/architecture-change-detection/06-pipeline-gates.md +0 -4
- package/dist/docs/development/guides/97-architecture-graph.md +1 -1
- package/dist/docs/development/guides/99-adding-analytics.md +0 -7
- package/dist/docs/development/guides/domains/03-model-subdomains.md +2 -2
- package/dist/docs/development/guides/domains/04-add-resources-to-domains/01-add-systems-to-domains.md +3 -1
- package/dist/docs/development/guides/domains/04-add-resources-to-domains/02-add-services-to-domains.md +5 -1
- package/dist/docs/development/guides/domains/04-add-resources-to-domains/03-add-messages-to-domains.md +2 -2
- package/dist/docs/development/guides/domains/04-add-resources-to-domains/05-add-entities-to-domains.md +1 -1
- package/dist/docs/development/guides/domains/04-add-resources-to-domains/06-domain-resources-page.md +40 -0
- package/dist/docs/development/guides/domains/06-visualize-domains/01-domain-diagram.md +89 -0
- package/dist/docs/development/guides/domains/06-visualize-domains/_category_.json +1 -2
- package/dist/docs/development/guides/domains/09-reference.md +4 -4
- package/dist/docs/development/guides/owners/automated-teams-and-users/create-your-own-connector.md +0 -2
- package/dist/docs/development/guides/owners/automated-teams-and-users/sync-from-github.md +0 -3
- package/dist/docs/development/guides/owners/automated-teams-and-users/sync-from-microsoft-entra.md +0 -2
- package/dist/docs/development/guides/resources/adrs/03-linking-resources.md +8 -0
- package/dist/docs/development/guides/resources/adrs/06-reference.md +4 -4
- package/dist/docs/development/guides/resources/agents/11-reference.md +1 -1
- package/dist/docs/development/guides/resources/data/04-reference.md +1 -1
- package/dist/docs/development/guides/resources/data-products/07-reference.md +1 -1
- package/dist/docs/development/guides/resources/entities/05-entity-maps.md +1 -1
- package/dist/docs/development/guides/resources/entities/06-reference.md +2 -2
- package/dist/docs/development/guides/resources/flows/01-introduction.md +11 -1
- package/dist/docs/development/guides/resources/flows/03-model-flow-steps.md +65 -6
- package/dist/docs/development/guides/resources/flows/05-explore-flows.md +112 -0
- package/dist/docs/development/guides/resources/flows/06-reference.md +25 -4
- package/dist/docs/development/guides/resources/messages/01-what-are-messages.md +19 -0
- package/dist/docs/development/guides/resources/messages/04-message-channels/01-introduction.md +16 -0
- package/dist/docs/development/guides/resources/messages/04-message-channels/05-reference.md +2 -1
- package/dist/docs/development/guides/resources/messages/10-reference.md +6 -3
- package/dist/docs/development/guides/resources/schemas/04-explore-schemas/01-schema-explorer.md +2 -2
- package/dist/docs/development/guides/resources/schemas/04-explore-schemas/02-fields-explorer.md +0 -9
- package/dist/docs/development/guides/resources/schemas/05-schema-api.md +0 -3
- package/dist/docs/development/guides/resources/schemas/06-schema-mcp.md +11 -3
- package/dist/docs/development/guides/resources/services/04-add-resources-to-services/03-add-entities-to-services.md +1 -1
- package/dist/docs/development/guides/resources/services/05-resources-page.md +50 -0
- package/dist/docs/development/guides/resources/services/08-reference.md +2 -1
- package/dist/docs/development/guides/systems/01-introduction.md +1 -1
- package/dist/docs/development/guides/systems/02-create-system.md +2 -2
- package/dist/docs/development/guides/systems/03-add-resources-to-systems.md +35 -9
- package/dist/docs/development/guides/systems/04-model-relationships-and-actors.md +5 -3
- package/dist/docs/development/guides/systems/05-system-context-maps.md +39 -22
- package/dist/docs/development/guides/systems/06-reference.md +4 -4
- package/dist/docs/development/license/01-license-file.md +151 -0
- package/dist/docs/development/license/_category_.json +12 -0
- package/dist/docs/development/license-keys/_category_.json +3 -3
- package/dist/docs/development/license-keys/integrations.md +7 -37
- package/dist/docs/development/license-keys/license-validation.md +4 -0
- package/dist/docs/development/license-keys/overview.md +5 -1
- package/dist/docs/development/license-keys/plans.md +4 -2
- package/dist/docs/development/studio/01-introduction.md +60 -0
- package/dist/docs/development/studio/02-create-a-canvas.md +103 -0
- package/dist/docs/development/studio/03-set-up-persistent-storage.md +59 -0
- package/dist/docs/development/studio/04-collaborate-on-a-canvas.md +78 -0
- package/dist/docs/development/studio/05-connect-your-agent.md +102 -0
- package/dist/docs/development/studio/06-run-studio-in-production.md +54 -0
- package/dist/docs/development/studio/07-reference.md +294 -0
- package/dist/docs/development/studio/_category_.json +12 -0
- package/dist/docs/development/upgrading/v5.md +345 -0
- package/dist/docs/federation/00-overview.md +2 -8
- package/dist/docs/federation/01-first-federation.md +6 -18
- package/dist/docs/federation/explanation/how-it-works.md +0 -4
- package/dist/docs/federation/explanation/lockfile-and-cache.md +0 -4
- package/dist/docs/federation/explanation/mvp-status-and-feedback.md +0 -4
- package/dist/docs/federation/explanation/ownership-and-references.md +0 -4
- package/dist/docs/federation/how-to/configure-github-sources.md +6 -5
- package/dist/docs/federation/how-to/configure-validation-rules.md +0 -4
- package/dist/docs/federation/how-to/run-in-ci.md +2 -9
- package/dist/docs/federation/how-to/share-assets-and-components.md +0 -4
- package/dist/docs/federation/how-to/use-local-sources.md +0 -4
- package/dist/docs/federation/legacy-federation/00-introduction.md +4 -22
- package/dist/docs/federation/legacy-federation/01-installation.md +7 -58
- package/dist/docs/federation/legacy-federation/02-plugin-configuration.md +3 -21
- package/dist/docs/federation/legacy-federation/03-examples.md +3 -5
- package/dist/docs/federation/legacy-federation/04-configuration.md +3 -8
- package/dist/docs/federation/legacy-federation/05-setup-team-catalog.md +3 -6
- package/dist/docs/federation/reference/cli.md +2 -8
- package/dist/docs/federation/reference/configuration.md +0 -4
- package/dist/docs/federation/reference/diagnostic-rules.md +0 -5
- package/dist/docs/federation/reference/generated-output.md +0 -4
- package/dist/docs/federation/reference/supported-content.md +0 -4
- package/dist/docs/federation/reference/troubleshooting.md +0 -14
- package/dist/docs/plugins/02-generators.md +1 -1
- package/dist/docs/plugins/amazon-apigateway/00-intro.md +3 -28
- package/dist/docs/plugins/amazon-apigateway/01-installation.md +4 -56
- package/dist/docs/plugins/amazon-apigateway/02-plugin-configuration.md +1 -6
- package/dist/docs/plugins/apicurio/00-intro.md +2 -31
- package/dist/docs/plugins/apicurio/01-installation.md +2 -26
- package/dist/docs/plugins/apicurio/02-plugin-configuration.md +5 -13
- package/dist/docs/plugins/apicurio/03-features.md +1 -3
- package/dist/docs/plugins/asyncapi/00-intro.md +2 -28
- package/dist/docs/plugins/asyncapi/01-installation.md +3 -54
- package/dist/docs/plugins/asyncapi/02-plugin-configuration.md +2 -1
- package/dist/docs/plugins/aws-glue-registry/00-intro.md +4 -32
- package/dist/docs/plugins/aws-glue-registry/00a-installation.md +3 -53
- package/dist/docs/plugins/azure-schema-registry/00-intro.md +4 -32
- package/dist/docs/plugins/azure-schema-registry/01-installation.md +6 -33
- package/dist/docs/plugins/azure-schema-registry/02-plugin-configuration.md +1 -14
- package/dist/docs/plugins/azure-schema-registry/04-examples.md +0 -2
- package/dist/docs/plugins/backstage/00-overview.md +1 -7
- package/dist/docs/plugins/backstage/01-get-started.md +6 -15
- package/dist/docs/plugins/backstage/06-configuration.md +2 -8
- package/dist/docs/plugins/confluent-schema-registry/00-intro.md +2 -29
- package/dist/docs/plugins/confluent-schema-registry/01-installation.md +2 -26
- package/dist/docs/plugins/eventbridge/00-intro.md +0 -4
- package/dist/docs/plugins/eventbridge/00a-installation.md +1 -87
- package/dist/docs/plugins/eventbridge/03-api.md +2 -20
- package/dist/docs/plugins/github/00-intro.md +0 -31
- package/dist/docs/plugins/github/01-installation.md +2 -34
- package/dist/docs/plugins/graphql/00-intro.md +0 -30
- package/dist/docs/plugins/graphql/01-installation.md +1 -53
- package/dist/docs/plugins/graphql/02-plugin-configuration.md +0 -1
- package/dist/docs/plugins/hookdeck/01-intro.md +1 -1
- package/dist/docs/plugins/openapi/00-intro.md +0 -30
- package/dist/docs/plugins/openapi/01-installation.md +1 -57
- package/dist/docs/plugins/openapi/02-plugin-configuration.md +0 -5
- package/dist/docs/plugins/openapi/03-features.md +0 -4
- package/dist/eventcatalog-config-file-utils.cjs +34 -41
- package/dist/eventcatalog-config-file-utils.d.cts +56 -58
- package/dist/eventcatalog-config-file-utils.d.ts +56 -58
- package/dist/eventcatalog-config-file-utils.js +1 -1
- package/dist/eventcatalog.cjs +340 -249
- package/dist/eventcatalog.config.d.cts +18 -15
- package/dist/eventcatalog.config.d.ts +18 -15
- package/dist/eventcatalog.js +51 -33
- package/dist/features.cjs +36 -49
- package/dist/features.d.cts +1 -3
- package/dist/features.d.ts +1 -3
- package/dist/features.js +4 -6
- package/dist/federation/federate.cjs +37 -44
- package/dist/federation/federate.js +5 -5
- package/dist/federation/source-provider.js +2 -2
- package/dist/generate.cjs +37 -42
- package/dist/generate.js +4 -4
- package/dist/resolve-catalog-dependencies.cjs +34 -41
- package/dist/resolve-catalog-dependencies.js +2 -2
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio-fonts.css.mjs +3 -0
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.css.mjs +3 -0
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.mjs +3 -0
- package/dist/runtime-dependencies/htmlparser2.mjs +3 -0
- package/dist/runtime-dependencies/manifest.json +5 -1
- package/dist/runtime-dependencies/react-syntax-highlighter__dist__cjs__create-element.js.mjs +3 -0
- package/dist/utils/child-process-signals.cjs +53 -0
- package/dist/utils/child-process-signals.d.cts +19 -0
- package/dist/utils/child-process-signals.d.ts +19 -0
- package/dist/utils/child-process-signals.js +6 -0
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/dist/utils/license-status.cjs +11 -4
- package/dist/utils/license-status.d.cts +3 -2
- package/dist/utils/license-status.d.ts +3 -2
- package/dist/utils/license-status.js +1 -1
- package/eventcatalog/astro.config.mjs +21 -1
- package/eventcatalog/integrations/config-loader.mjs +56 -58
- package/eventcatalog/integrations/skip-startup-reload.mjs +31 -0
- package/eventcatalog/integrations/stable-dependency-order.mjs +29 -0
- package/eventcatalog/integrations/storage.mjs +20 -0
- package/eventcatalog/integrations/studio-server.mjs +4 -1
- package/eventcatalog/src/components/CatalogGraph/CatalogForceGraph.tsx +39 -0
- package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +2 -0
- package/eventcatalog/src/components/Homepage/CatalogDashboard.astro +342 -0
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +60 -4
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -1
- package/eventcatalog/src/components/NavigationProgress.astro +7 -0
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaCodeModal.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -0
- package/eventcatalog/src/components/Search/SearchDataLoader.astro +16 -28
- package/eventcatalog/src/components/Search/SearchModal.tsx +2 -10
- package/eventcatalog/src/components/Search/search-utils.ts +26 -0
- package/eventcatalog/src/components/Seo.astro +5 -1
- package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +53 -48
- package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +183 -178
- package/eventcatalog/src/components/Settings/LicenseSettings.tsx +140 -31
- package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +40 -35
- package/eventcatalog/src/components/Settings/LogoUpload.tsx +1 -1
- package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +9 -8
- package/eventcatalog/src/components/Settings/Row.tsx +7 -4
- package/eventcatalog/src/components/Settings/SettingsShared.tsx +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +37 -76
- package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +2 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +122 -1
- package/eventcatalog/src/components/SideNav/SideNav.astro +9 -1
- package/eventcatalog/src/components/TrialBadge.astro +20 -9
- package/eventcatalog/src/content.config.ts +19 -2
- package/eventcatalog/src/features/auth/error.astro +4 -2
- package/eventcatalog/src/features/auth/login.astro +2 -1
- package/eventcatalog/src/features/auth/middleware/middleware-auth.ts +21 -1
- package/eventcatalog/src/features/auth/unauthorized.astro +1 -1
- package/eventcatalog/src/features/fields/pages/fields.astro +1 -1
- package/eventcatalog/src/features/integrations/eventcatalog-features.ts +13 -7
- package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +6 -45
- package/eventcatalog/src/features/mcp/apps/canvas/shared.ts +3 -3
- package/eventcatalog/src/features/mcp/apps/canvas/styles.css +3 -1
- package/eventcatalog/src/features/mcp/apps/canvas/view.tsx +7 -5
- package/eventcatalog/src/features/mcp/apps/generated/canvas.html +123 -98
- package/eventcatalog/src/features/mcp/apps/generated/viewer.html +118 -101
- package/eventcatalog/src/features/mcp/mcp-server.ts +20 -4
- package/eventcatalog/src/features/server/start.ts +25 -0
- package/eventcatalog/src/features/storage/database.ts +88 -0
- package/eventcatalog/src/features/storage/migrations.ts +85 -0
- package/eventcatalog/src/features/storage/sql/database.sql +5 -0
- package/eventcatalog/src/features/storage/sql/migrations/0001-studio-canvases.sql +12 -0
- package/eventcatalog/src/features/storage/sql/migrations.sql +15 -0
- package/eventcatalog/src/features/storage/sql.ts +28 -0
- package/eventcatalog/src/features/studio/agent-choreography.ts +13 -10
- package/eventcatalog/src/features/studio/agents.ts +28 -0
- package/eventcatalog/src/features/studio/api/canvases-api.ts +219 -0
- package/eventcatalog/src/features/studio/api/canvases.ts +25 -0
- package/eventcatalog/src/features/studio/api/client.ts +40 -0
- package/eventcatalog/src/features/studio/canvas-actions.ts +160 -34
- package/eventcatalog/src/features/studio/canvas-preview.ts +1 -2
- package/eventcatalog/src/features/studio/catalog.ts +16 -14
- package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +274 -105
- package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +15 -14
- package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +272 -119
- package/eventcatalog/src/features/studio/components/ConnectionsChooser.tsx +1 -2
- package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +65 -0
- package/eventcatalog/src/features/studio/components/Dialog.tsx +60 -0
- package/eventcatalog/src/features/studio/components/JoinForm.tsx +101 -26
- package/eventcatalog/src/features/studio/components/LeftPanel.tsx +122 -230
- package/eventcatalog/src/features/studio/components/NodeDetails.tsx +183 -0
- package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +79 -0
- package/eventcatalog/src/features/studio/components/Presence.tsx +52 -45
- package/eventcatalog/src/features/studio/components/ShareDialog.tsx +277 -141
- package/eventcatalog/src/features/studio/components/ShortcutsDialog.tsx +41 -0
- package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +1314 -385
- package/eventcatalog/src/features/studio/components/StudioNotice.astro +24 -0
- package/eventcatalog/src/features/studio/document-name.ts +7 -0
- package/eventcatalog/src/features/studio/from-visualiser.ts +138 -0
- package/eventcatalog/src/features/studio/hooks/presence-sender.ts +19 -2
- package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +9 -3
- package/eventcatalog/src/features/studio/hooks/use-comments.ts +2 -2
- package/eventcatalog/src/features/studio/hooks/use-follow-camera.ts +8 -3
- package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +244 -32
- package/eventcatalog/src/features/studio/identity.ts +25 -1
- package/eventcatalog/src/features/studio/limits.ts +2 -0
- package/eventcatalog/src/features/studio/pages/[id].astro +42 -16
- package/eventcatalog/src/features/studio/pages/index.astro +596 -373
- package/eventcatalog/src/features/studio/pages/webmcp-relay.ts +12 -15
- package/eventcatalog/src/features/studio/server/canvas-mcp.ts +8 -23
- package/eventcatalog/src/features/studio/server/runtime.ts +150 -46
- package/eventcatalog/src/features/studio/server/sql/storage.sql +18 -0
- package/eventcatalog/src/features/studio/server/storage.ts +53 -73
- package/eventcatalog/src/features/studio/webmcp-relay/LICENSE +21 -0
- package/eventcatalog/src/features/studio/webmcp-relay/README.md +5 -0
- package/eventcatalog/src/features/studio/webmcp-relay/embed.js +2 -0
- package/eventcatalog/src/features/studio/webmcp-relay/widget.html +10 -0
- package/eventcatalog/src/features/studio/webmcp-relay/widget.js +1 -0
- package/eventcatalog/src/features/tools/catalog-tools.ts +3 -1
- package/eventcatalog/src/layouts/BaseLayout.astro +4 -4
- package/eventcatalog/src/layouts/SettingsLayout.astro +2 -2
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +3 -2
- package/eventcatalog/src/pages/_index.astro +5 -342
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.spec.ts +2 -3
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -1
- package/eventcatalog/src/pages/diagrams/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/diagrams/[id]/[version]/embed.astro +1 -0
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/directory/[type]/_index.data.ts +5 -7
- package/eventcatalog/src/pages/directory/[type]/index.astro +3 -1
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -7
- package/eventcatalog/src/pages/discover/[type]/index.astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/_[...filename].data.ts +0 -4
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.spec.ts +2 -3
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +2 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +1 -0
- package/eventcatalog/src/pages/docs/custom/[...path]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/[version]/resources/index.astro +1 -0
- package/eventcatalog/src/pages/docs/services/[id]/asyncapi/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/changelog/index.astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/graphql/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/spec/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/index.astro +4 -2
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +9 -1
- package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +0 -7
- package/eventcatalog/src/pages/schemas/explorer/index.astro +4 -2
- package/eventcatalog/src/pages/settings/license.astro +9 -1
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/_index.data.ts +38 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +18 -41
- package/eventcatalog/src/pages/visualiser/designs/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -1
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/types/react-syntax-highlighter.d.ts +10 -0
- package/eventcatalog/src/utils/collections/flows.ts +20 -7
- package/eventcatalog/src/utils/collections/resource-owners.ts +8 -2
- package/eventcatalog/src/utils/collections/resources.ts +2 -0
- package/eventcatalog/src/utils/collections/util.ts +8 -4
- package/eventcatalog/src/utils/git.ts +11 -0
- package/eventcatalog/src/utils/homepage-dashboard.ts +143 -0
- package/eventcatalog/src/utils/license.ts +1 -1
- package/eventcatalog/src/utils/link-validation.ts +25 -19
- package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +3 -1
- package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +3 -3
- package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +4 -2
- package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +20 -1
- package/eventcatalog/src/utils/node-graphs/node-resource.ts +67 -0
- package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +1 -1
- package/eventcatalog/src/utils/page-loaders/hybrid-page.ts +4 -15
- package/eventcatalog/src/utils/page-title.ts +15 -0
- package/eventcatalog/src/utils/syntax-highlighter-renderer.ts +64 -0
- package/eventcatalog/src/utils/trial.ts +13 -0
- package/package.json +11 -11
- package/dist/docs/development/ask-your-architecture/05-skills/02-installation.md +0 -60
- package/dist/docs/development/ask-your-architecture/05-skills/_category_.json +0 -11
- package/dist/docs/development/ask-your-architecture/06-slack-integration/01-introduction.md +0 -63
- package/dist/docs/development/ask-your-architecture/06-slack-integration/02-slack-app-setup.md +0 -154
- package/dist/docs/development/ask-your-architecture/06-slack-integration/03-installation.md +0 -169
- package/dist/docs/development/ask-your-architecture/06-slack-integration/04-deployment.md +0 -236
- package/dist/docs/development/ask-your-architecture/06-slack-integration/05-usage.md +0 -140
- package/dist/docs/development/ask-your-architecture/06-slack-integration/06-troubleshooting.md +0 -268
- package/dist/docs/development/ask-your-architecture/06-slack-integration/_category_.json +0 -13
- package/dist/docs/development/guides/domains/06-visualize-domains/01-domain-integration-map.md +0 -40
- package/dist/runtime-dependencies/@mcp-b__webmcp-local-relay.mjs +0 -3
- package/eventcatalog/src/features/studio/canvas-doc.ts +0 -409
- package/eventcatalog/src/features/studio/clipboard.ts +0 -97
- package/eventcatalog/src/features/studio/components/CanvasControls.tsx +0 -154
- package/eventcatalog/src/features/studio/components/Comments.tsx +0 -770
- package/eventcatalog/src/features/studio/components/ContainerChooser.tsx +0 -145
- package/eventcatalog/src/features/studio/components/DragGhost.tsx +0 -115
- package/eventcatalog/src/features/studio/components/Picture.tsx +0 -21
- package/eventcatalog/src/features/studio/components/PropertiesPanel.tsx +0 -212
- package/eventcatalog/src/features/studio/components/canvas-nodes.tsx +0 -255
- package/eventcatalog/src/features/studio/components/icons.ts +0 -53
- package/eventcatalog/src/features/studio/components/status.ts +0 -51
- package/eventcatalog/src/features/studio/edges.ts +0 -56
- package/eventcatalog/src/features/studio/flow-state.ts +0 -92
- package/eventcatalog/src/features/studio/grouping.ts +0 -226
- package/eventcatalog/src/features/studio/layout.ts +0 -42
- package/eventcatalog/src/features/studio/levels.ts +0 -282
- package/eventcatalog/src/features/studio/node-types.ts +0 -205
- package/eventcatalog/src/features/studio/pages/new.astro +0 -24
- package/eventcatalog/src/features/studio/pages/wake.ts +0 -15
- package/eventcatalog/src/features/studio/placement.ts +0 -197
- package/eventcatalog/src/features/studio/studio.css +0 -273
- package/dist/{chunk-A2RZR3U4.js → chunk-6K7XZAYI.js} +3 -3
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# WebMCP local relay (browser files)
|
|
2
|
+
|
|
3
|
+
`embed.js`, `widget.html` and `widget.js` are the browser files of [`@mcp-b/webmcp-local-relay`](https://github.com/WebMCP-org/npm-packages/tree/main/packages/webmcp-local-relay) **5.1.0** (MIT, see `LICENSE`), copied as published. Studio serves them at `/webmcp-relay/*` so a canvas can hand its WebMCP tools to desktop MCP clients running `npx -y @mcp-b/webmcp-local-relay@5.1.0`.
|
|
4
|
+
|
|
5
|
+
They're copied rather than installed because the package's Node dependencies (which EventCatalog doesn't run) pin vulnerable versions of `@modelcontextprotocol/core` and `zod`. When moving to a new relay version, copy its `dist/browser` files here and update the version in `ConnectAgentDialog.tsx`.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){function e(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function t(t){if(!e(t))return!1;let n=Object.getPrototypeOf(t);return n===Object.prototype||n===null}function n(e,r=new WeakSet){if(e===null||typeof e==`string`||typeof e==`boolean`)return!0;if(typeof e==`number`)return Number.isFinite(e);if(typeof e!=`object`||r.has(e))return!1;r.add(e);try{return(Array.isArray(e)?e:t(e)?Object.values(e):null)?.every(e=>n(e,r))??!1}catch{return!1}finally{r.delete(e)}}function r(e){return n(e)?e:void 0}function i(t){return e(t)&&Array.isArray(t.content)}function a(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}}function o(e){if(i(e))return e;let t=r(e);return{content:[{type:`text`,text:a(e)}],...t===void 0?{}:{structuredContent:t},isError:!1}}function s(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function c(){return crypto.randomUUID()}let l=`[data-webmcp-relay]`,u=`__webmcp_relay_tab_id`,d=null,f;function p(){return document.currentScript instanceof HTMLScriptElement?document.currentScript:null}let m=p(),h=m?m.hasAttribute(`data-debug`):!1;function g(...e){h&&console.warn(`[webmcp-relay-embed]`,...e)}function _(){try{let e=sessionStorage.getItem(u);if(e)return e}catch(e){g(`sessionStorage read failed, tab ID will not persist:`,e)}let e=c();try{sessionStorage.setItem(u,e)}catch(e){g(`sessionStorage write failed:`,e)}return e}function v(e){if(!e?.src)throw Error(`The relay embed script must be loaded from a URL`);return new URL(`widget.html`,e.src).href}function y(e){let t=v(e),n=e?.getAttribute(`data-relay-id`)||void 0,r=e?.getAttribute(`data-relay-workspace`)||void 0,i=e?.getAttribute(`data-request-timeout`)||void 0;return{autoConnect:e?.getAttribute(`data-auto-connect`)!==`false`,relayHost:e?.getAttribute(`data-relay-host`)||`127.0.0.1`,relayPort:e?.getAttribute(`data-relay-port`)||`9333`,...n?{relayId:n}:{},...r?{relayWorkspace:r}:{},...i?{requestTimeout:i}:{},tabId:_(),widgetUrl:t,widgetOrigin:new URL(t).origin}}function b(e){return s(e)?e:(e!=null&&g(`Tool invocation args must be an object, got`,typeof e),{})}function x(e){let t;if(e.inputSchema!==void 0)if(typeof e.inputSchema==`string`)try{t=JSON.parse(e.inputSchema)}catch{return console.warn(`[webmcp-relay-embed] Tool "${e.name}" was not relayed because its input schema is malformed.`),null}else t=e.inputSchema;return{name:e.name,...e.title===void 0?{}:{title:e.title},description:e.description,...t===void 0?{}:{inputSchema:t},...e.annotations===void 0?{}:{annotations:e.annotations}}}function S(e){if(e===null)return{isError:!0,content:[{type:`text`,text:`Tool execution interrupted by navigation`}]};let t;try{t=JSON.parse(e)}catch{t=e}return s(t)&&t.resultType===`input_required`?{isError:!0,content:[{type:`text`,text:`The WebMCP local relay cannot forward MCP input_required results. Multi-round tool flows require direct McpServer registration.`}]}:o(t)}function C(e){return!!(e&&`executeTool`in e&&typeof e.executeTool==`function`)}function w(){let e=document.modelContext;return C(e)?e:void 0}async function T(){let e=w();return e?(await e.getTools()).map(x).filter(e=>e!==null):[]}async function E(e,t){let n=w();if(!n)throw Error(`No executable WebMCP runtime found on this page`);let r=(await n.getTools()).find(t=>t.name===e);if(!r)throw Error(`Tool not found: ${e}`);return S(await n.executeTool(r,JSON.stringify(t)))}let D=!1,O=0,k=null,A=``;function j(e){if(typeof e!=`object`||!e)return JSON.stringify(e)??`undefined`;if(Array.isArray(e))return`[${e.map(j).join(`,`)}]`;let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${j(t[e])}`).join(`,`)}}`}function M(e){return e.map(j).sort().join(`
|
|
2
|
+
`)}function N(){D=!1;let e=O;T().then(t=>{if(e!==O)return;let n=M(t);n===A||!d||(A=n,d.postMessage({type:`webmcp.tools.changed`,tools:t},f.widgetOrigin))}).catch(e=>{g(`Failed to sync tool changes:`,e)})}function P(){O++,!D&&(D=!0,setTimeout(N,0))}function F(){k||(k=setInterval(P,2e3))}function I(){try{let e=document.modelContext;return e?(e.addEventListener(`toolchange`,P),!0):!1}catch(e){return g(`addEventListener on modelContext threw:`,e),!1}}function L(){if(F(),P(),I())return;let e=0,t=100,n=()=>{setTimeout(()=>{if(e++,!I()){if(e>=40){g(`Could not subscribe to tool changes after 40 retries. Dynamic tool updates will rely on polling.`);return}t=Math.min(Math.round(t*1.5),1e3),n()}},t)};n()}function R(e,t,n){!e||typeof e!=`object`||!(`postMessage`in e)||e.postMessage(n,t)}function z(e){return!s(e)||typeof e.requestId!=`string`||typeof e.type!=`string`?null:{requestId:e.requestId,type:e.type,toolName:e.toolName,args:e.args}}function B(e,t){T().then(n=>{R(t.source,t.origin,{type:`webmcp.tools.list.response`,requestId:e.requestId,tools:n})}).catch(n=>{g(`Failed to list tools:`,n),R(t.source,t.origin,{type:`webmcp.tools.list.response`,requestId:e.requestId,tools:[],error:`Failed to list tools: ${n instanceof Error?n.message:String(n)}`})})}function V(e,t){E(String(e.toolName??``),b(e.args)).then(n=>{R(t.source,t.origin,{type:`webmcp.tools.invoke.response`,requestId:e.requestId,result:s(n)?n:{}})}).catch(n=>{R(t.source,t.origin,{type:`webmcp.tools.invoke.error`,requestId:e.requestId,error:String(n instanceof Error?n.message:n)})})}async function H(e){if(document.querySelector(l))return;let t=new URLSearchParams;t.set(`tabId`,e.tabId),t.set(`hostOrigin`,window.location.origin);let n=new URL(window.location.href);n.search=``,n.hash=``,t.set(`hostUrl`,n.href),t.set(`hostTitle`,document.title||``),t.set(`relayHost`,e.relayHost),t.set(`relayPort`,e.relayPort),t.set(`autoConnect`,e.autoConnect?`true`:`false`),e.relayId&&t.set(`relayId`,e.relayId),e.relayWorkspace&&t.set(`relayWorkspace`,e.relayWorkspace),e.requestTimeout&&t.set(`requestTimeout`,e.requestTimeout);let r=await fetch(e.widgetUrl);if(!r.ok)throw Error(`Widget HTML request failed with status ${String(r.status)}`);let i=await r.text(),a=`<script>window.__WEBMCP_RELAY_CONFIG=${JSON.stringify(Object.fromEntries(t))};<\/script>`,o=URL.createObjectURL(new Blob([i.replace(`</head>`,`${a}</head>`)],{type:`text/html`}));e.widgetOrigin=window.location.origin;let s=document.createElement(`iframe`);s.src=o,s.style.display=`none`,s.setAttribute(`aria-hidden`,`true`),s.setAttribute(`data-webmcp-relay`,`1`),s.setAttribute(`allow`,`loopback-network; local-network; local-network-access`),document.body.appendChild(s),d=s.contentWindow,s.addEventListener(`load`,()=>{d=s.contentWindow,URL.revokeObjectURL(o)}),s.addEventListener(`error`,()=>{console.error(`[webmcp-relay-embed] Failed to load relay widget iframe from:`,s.src,`-- WebMCP tools will NOT be relayed. Check network connectivity and widget URL.`),URL.revokeObjectURL(o)})}if(!document.querySelector(l)){try{f=y(m)}catch(e){throw console.error(`[webmcp-relay-embed] Failed to initialize relay configuration:`,e),e}window.addEventListener(`message`,e=>{if(e.origin!==f.widgetOrigin||!d||e.source!==d)return;let t=e.data;if(s(t)&&t.type===`webmcp.reload`){window.location.reload();return}let n=z(e.data);if(n){if(n.type===`webmcp.tools.list.request`){B(n,e);return}n.type===`webmcp.tools.invoke.request`&&V(n,e)}});let e=()=>{H(f).catch(e=>{console.error(`[webmcp-relay-embed] Failed to inject relay widget:`,e)})};document.body?e():document.addEventListener(`DOMContentLoaded`,e,{once:!0}),L(),document.addEventListener(`visibilitychange`,()=>{document.visibilityState===`visible`&&d&&d.postMessage({type:`webmcp.connect`},f.widgetOrigin)})}})();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>WebMCP Relay Widget</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<script>(function(){let e=new Set([`127.0.0.1`,`localhost`,`::1`,`[::1]`]),t=9333;function n(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function r(t){return e.has(t)}function i(){return crypto.randomUUID()}function a(e){return String(e).replace(/[\r\n]/g,``)}function o(e,t){try{e.readyState===WebSocket.OPEN&&e.send(t)}catch(e){console.warn(`[webmcp-relay] Failed to send message:`,e)}}function s(e){return`__webmcp_relay_endpoint:${[e.hostOrigin,e.relayId??``,e.workspace??``].map(e=>encodeURIComponent(e)).join(`:`)}`}let c=[1e4,2e4,3e4];function l(e=window.location.search){let n=new URLSearchParams(e),a=globalThis.__WEBMCP_RELAY_CONFIG;function o(e){return n.get(e)??a?.[e]??null}let s=o(`hostOrigin`);if(!s)return null;let c=o(`hostUrl`)||s,l=o(`hostTitle`)||``,u=o(`tabId`)||i(),d=o(`relayHost`)||`127.0.0.1`,f=o(`relayPort`),p=f&&f.length>0?Number(f):t,m=o(`autoConnect`)!==`false`,h=o(`relayId`)||void 0,g=o(`relayWorkspace`)||void 0,_=o(`requestTimeout`),v=_&&_.length>0?Number(_):6e4;return r(d)?!Number.isInteger(p)||p<1||p>65535?(console.error(`[webmcp-relay-widget] relayPort must be an integer between 1 and 65535, got:`,f),null):!Number.isInteger(v)||v<1?(console.error(`[webmcp-relay-widget] requestTimeout must be a positive integer (ms), got:`,_),null):{autoConnect:m,hostOrigin:s,hostTitle:l,hostUrl:c,relayHostHint:d,relayPortHint:p,...h?{relayId:h}:{},...g?{relayWorkspace:g}:{},requestTimeoutMs:v,tabId:u}:(console.error(`[webmcp-relay-widget] relayHost must be a loopback address, got:`,d),null)}function u(e){return!n(e)||typeof e.requestId!=`string`||typeof e.type!=`string`?null:{requestId:e.requestId,type:e.type,tools:e.tools,result:e.result,error:e.error}}function d(){let e=l();if(!e){console.warn(`[webmcp-relay-widget] Missing required hostOrigin parameter. Widget will not start.`);return}b(e)}function f(e){return!n(e)||e.type!==`server-hello`||e.service!==`webmcp-local-relay`||e.version!==1||typeof e.host!=`string`||typeof e.instanceId!=`string`||typeof e.port!=`number`?null:{type:`server-hello`,service:`webmcp-local-relay`,version:1,host:e.host,instanceId:e.instanceId,port:e.port,...typeof e.label==`string`?{label:e.label}:{},...typeof e.relayId==`string`?{relayId:e.relayId}:{},...typeof e.workspace==`string`?{workspace:e.workspace}:{}}}function p(e){return!n(e)||e.type!==`hello/rejected`||typeof e.message!=`string`||typeof e.reason!=`string`?null:{type:`hello/rejected`,message:e.message,reason:e.reason}}function m(e){return s({hostOrigin:e.hostOrigin,...e.relayId?{relayId:e.relayId}:{},...e.relayWorkspace?{workspace:e.relayWorkspace}:{}})}function h(e){if(typeof sessionStorage>`u`)return null;try{let t=sessionStorage.getItem(m(e));if(!t)return null;let n=JSON.parse(t);return typeof n.host!=`string`||n.host.length===0||typeof n.port!=`number`||!Number.isInteger(n.port)||n.port<1||n.port>65535?null:{host:n.host,port:n.port}}catch{return null}}function g(e,t){if(!(typeof sessionStorage>`u`))try{sessionStorage.setItem(m(e),JSON.stringify({host:t.host,port:t.port}))}catch{}}function _(e){if(!(typeof sessionStorage>`u`))try{sessionStorage.removeItem(m(e))}catch{}}function v(e){let n=h(e),r=new Set,i=[],a=(e,t)=>{if(!Number.isInteger(t)||t<1||t>65535)return;let n=`${e}:${String(t)}`;r.has(n)||(r.add(n),i.push({host:e,port:t}))};e.relayPortHint!==void 0&&a(e.relayHostHint,e.relayPortHint),n&&a(n.host,n.port);for(let e of[`127.0.0.1`,`[::1]`])for(let n=t;n<=9348;n+=1)a(e,n);return i}async function y(e){let t=`ws://${e.host.includes(`:`)&&!e.host.startsWith(`[`)?`[${e.host}]`:e.host}:${String(e.port)}`;return new Promise(n=>{let r=!1,i=new WebSocket(t,[`webmcp-discovery.v1`,`webmcp.v1`]),a=e=>{if(!r){if(r=!0,clearTimeout(l),i.removeEventListener(`close`,s),i.removeEventListener(`error`,o),i.removeEventListener(`message`,c),e===null)try{i.close()}catch{}n(e)}},o=()=>{a(null)},s=()=>{a(null)},c=t=>{let n;try{n=JSON.parse(String(t.data))}catch{return}let r=f(n);r&&a({endpoint:{hello:r,host:e.host,port:e.port},socket:i})},l=setTimeout(()=>{a(null)},1200);i.addEventListener(`close`,s,{once:!0}),i.addEventListener(`error`,o,{once:!0}),i.addEventListener(`message`,c)})}function b(e){let t=new Map,r=null,s=null,l=!1,d=null,m=null,b=`idle`,x=0,S=null,C=e=>{for(let[n,r]of t)clearTimeout(r.timeoutId),t.delete(n),r.reject(Error(e))};function w(n,r){let a=i();return new Promise((i,o)=>{let s=setTimeout(()=>{t.delete(a),o(Error(`Host response timeout: ${n}`))},e.requestTimeoutMs);t.set(a,{resolve:i,reject:o,timeoutId:s,responseType:`${n}.response`,errorType:`${n}.error`}),window.parent.postMessage({type:`${n}.request`,requestId:a,...r},e.hostOrigin)})}let T=(t,i)=>{let c=[],u=()=>{d&&(clearTimeout(d),d=null)},h=()=>{o(t,JSON.stringify({type:`tools/list`,tools:c}))};m&&(clearTimeout(m),m=null),r=i,s=t,x=0,l=!1,b=`idle`,t.addEventListener(`message`,s=>{let c;try{c=JSON.parse(String(s.data))}catch(e){console.warn(`[webmcp-relay-widget] Failed to parse relay message:`,e);return}let d=f(c);if(d){r={hello:d,host:i.host,port:i.port};return}if(n(c)&&c.type===`hello/accepted`){u(),l=!0,g(e,i),h();return}let m=p(c);if(m){u(),l=!1,_(e),window.parent.postMessage({type:`webmcp.relay.rejected`,host:i.host,port:i.port,message:m.message,reason:m.reason},e.hostOrigin),console.error(`[webmcp-relay-widget] Relay rejected browser hello:`,m.reason,m.message);try{t.close(1008,m.message)}catch{}return}if(!n(c)||typeof c.type!=`string`)return;let v=c;if(v.type===`ping`){o(t,JSON.stringify({type:`pong`}));return}if(v.type===`reload`){window.parent.postMessage({type:`webmcp.reload`},e.hostOrigin);return}if(v.type!==`invoke`){console.debug(`[webmcp-relay-widget] Ignoring unrecognized message type:`,a(v.type));return}w(`webmcp.tools.invoke`,{toolName:v.toolName,args:n(v.args)?v.args:{}}).then(e=>{o(t,JSON.stringify({type:`result`,callId:v.callId,result:e.result}))}).catch(e=>{o(t,JSON.stringify({type:`result`,callId:v.callId,result:{isError:!0,content:[{type:`text`,text:String(e instanceof Error?e.message:e)}]}}))})}),t.addEventListener(`close`,()=>{s===t&&(l=!1,s=null,u(),C(`WebSocket connection lost`),O())},{once:!0}),t.addEventListener(`error`,e=>{console.warn(`[webmcp-relay-widget] WebSocket error:`,e);try{t.close()}catch(e){console.warn(`[webmcp-relay-widget] Error closing socket after error:`,e)}}),w(`webmcp.tools.list`,{}).then(n=>{c=Array.isArray(n.tools)?n.tools:[],o(t,JSON.stringify({type:`hello`,tabId:e.tabId,origin:e.hostOrigin,title:e.hostTitle||document.referrer||`Unknown page`,url:e.hostUrl})),d=setTimeout(()=>{d=null,!(s!==t||t.readyState!==WebSocket.OPEN||l)&&(console.warn(`[webmcp-relay-widget] Relay did not acknowledge browser hello`),t.close(4e3,`Browser hello was not acknowledged`))},1e3)}).catch(e=>{console.warn(`[webmcp-relay-widget] Hello handshake failed:`,e);try{t.close()}catch{}})},E=async t=>{let n=await y({host:t.host,port:t.port});if(!n)return!1;let r=n.endpoint;return e.relayId&&r.hello.relayId!==e.relayId||e.relayWorkspace&&r.hello.workspace!==e.relayWorkspace?(n.socket.close(),!1):(T(n.socket,r),!0)},D=async()=>{b=`discovering`;try{for(let t of v(e))if(await E(t))return!0;return!1}finally{b===`discovering`&&(b=`idle`)}},O=()=>{if(!r||m)return;let e={host:r.host,port:r.port},t=Math.round(500*(.85+Math.random()*.3));m=setTimeout(()=>{m=null,E(e).then(e=>{e||k()})},t)},k=()=>{if(m)return;let e=c[x];if(e===void 0){M();return}m=setTimeout(()=>{m=null,D().then(e=>{e||(x+=1,k())})},e)},A=()=>{document.visibilityState===`visible`&&b===`dormant`&&P()},j=()=>{document.removeEventListener(`visibilitychange`,A),S!==null&&(clearInterval(S),S=null)},M=()=>{b!==`dormant`&&(b=`dormant`,m&&(clearTimeout(m),m=null),document.addEventListener(`visibilitychange`,A),S=setInterval(()=>{N()},12e4))},N=async()=>{if(b!==`dormant`)return;let t=new Set,n=[],r=(e,r)=>{let i=`${e}:${String(r)}`;t.has(i)||(t.add(i),n.push({host:e,port:r}))};e.relayPortHint!==void 0&&r(e.relayHostHint,e.relayPortHint);let i=h(e);if(i&&r(i.host,i.port),n.length!==0){b=`discovering`,j();for(let e of n)if(await E(e)){x=0;return}M()}},P=()=>{j(),x=0,D().then(e=>{e||M()})};window.addEventListener(`message`,r=>{if(r.source!==window.parent||r.origin!==e.hostOrigin)return;let i=r.data;if(n(i)&&i.type===`webmcp.tools.changed`){s&&l&&o(s,JSON.stringify({type:`tools/changed`,tools:Array.isArray(i.tools)?i.tools:[]}));return}if(n(i)&&i.type===`webmcp.connect`){b===`dormant`?P():!s&&b!==`discovering`&&D();return}let a=u(i);if(!a)return;let c=t.get(a.requestId);if(c){if(a.type===c.responseType){clearTimeout(c.timeoutId),t.delete(a.requestId),c.resolve(a);return}a.type===c.errorType&&(clearTimeout(c.timeoutId),t.delete(a.requestId),c.reject(Error(String(a.error||`Unknown host error`))))}}),e.autoConnect&&D().then(e=>{e||k()})}d()})();</script>
|
|
9
|
+
</body>
|
|
10
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){let e=new Set([`127.0.0.1`,`localhost`,`::1`,`[::1]`]),t=9333;function n(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function r(t){return e.has(t)}function i(){return crypto.randomUUID()}function a(e){return String(e).replace(/[\r\n]/g,``)}function o(e,t){try{e.readyState===WebSocket.OPEN&&e.send(t)}catch(e){console.warn(`[webmcp-relay] Failed to send message:`,e)}}function s(e){return`__webmcp_relay_endpoint:${[e.hostOrigin,e.relayId??``,e.workspace??``].map(e=>encodeURIComponent(e)).join(`:`)}`}let c=[1e4,2e4,3e4];function l(e=window.location.search){let n=new URLSearchParams(e),a=globalThis.__WEBMCP_RELAY_CONFIG;function o(e){return n.get(e)??a?.[e]??null}let s=o(`hostOrigin`);if(!s)return null;let c=o(`hostUrl`)||s,l=o(`hostTitle`)||``,u=o(`tabId`)||i(),d=o(`relayHost`)||`127.0.0.1`,f=o(`relayPort`),p=f&&f.length>0?Number(f):t,m=o(`autoConnect`)!==`false`,h=o(`relayId`)||void 0,g=o(`relayWorkspace`)||void 0,_=o(`requestTimeout`),v=_&&_.length>0?Number(_):6e4;return r(d)?!Number.isInteger(p)||p<1||p>65535?(console.error(`[webmcp-relay-widget] relayPort must be an integer between 1 and 65535, got:`,f),null):!Number.isInteger(v)||v<1?(console.error(`[webmcp-relay-widget] requestTimeout must be a positive integer (ms), got:`,_),null):{autoConnect:m,hostOrigin:s,hostTitle:l,hostUrl:c,relayHostHint:d,relayPortHint:p,...h?{relayId:h}:{},...g?{relayWorkspace:g}:{},requestTimeoutMs:v,tabId:u}:(console.error(`[webmcp-relay-widget] relayHost must be a loopback address, got:`,d),null)}function u(e){return!n(e)||typeof e.requestId!=`string`||typeof e.type!=`string`?null:{requestId:e.requestId,type:e.type,tools:e.tools,result:e.result,error:e.error}}function d(){let e=l();if(!e){console.warn(`[webmcp-relay-widget] Missing required hostOrigin parameter. Widget will not start.`);return}b(e)}function f(e){return!n(e)||e.type!==`server-hello`||e.service!==`webmcp-local-relay`||e.version!==1||typeof e.host!=`string`||typeof e.instanceId!=`string`||typeof e.port!=`number`?null:{type:`server-hello`,service:`webmcp-local-relay`,version:1,host:e.host,instanceId:e.instanceId,port:e.port,...typeof e.label==`string`?{label:e.label}:{},...typeof e.relayId==`string`?{relayId:e.relayId}:{},...typeof e.workspace==`string`?{workspace:e.workspace}:{}}}function p(e){return!n(e)||e.type!==`hello/rejected`||typeof e.message!=`string`||typeof e.reason!=`string`?null:{type:`hello/rejected`,message:e.message,reason:e.reason}}function m(e){return s({hostOrigin:e.hostOrigin,...e.relayId?{relayId:e.relayId}:{},...e.relayWorkspace?{workspace:e.relayWorkspace}:{}})}function h(e){if(typeof sessionStorage>`u`)return null;try{let t=sessionStorage.getItem(m(e));if(!t)return null;let n=JSON.parse(t);return typeof n.host!=`string`||n.host.length===0||typeof n.port!=`number`||!Number.isInteger(n.port)||n.port<1||n.port>65535?null:{host:n.host,port:n.port}}catch{return null}}function g(e,t){if(!(typeof sessionStorage>`u`))try{sessionStorage.setItem(m(e),JSON.stringify({host:t.host,port:t.port}))}catch{}}function _(e){if(!(typeof sessionStorage>`u`))try{sessionStorage.removeItem(m(e))}catch{}}function v(e){let n=h(e),r=new Set,i=[],a=(e,t)=>{if(!Number.isInteger(t)||t<1||t>65535)return;let n=`${e}:${String(t)}`;r.has(n)||(r.add(n),i.push({host:e,port:t}))};e.relayPortHint!==void 0&&a(e.relayHostHint,e.relayPortHint),n&&a(n.host,n.port);for(let e of[`127.0.0.1`,`[::1]`])for(let n=t;n<=9348;n+=1)a(e,n);return i}async function y(e){let t=`ws://${e.host.includes(`:`)&&!e.host.startsWith(`[`)?`[${e.host}]`:e.host}:${String(e.port)}`;return new Promise(n=>{let r=!1,i=new WebSocket(t,[`webmcp-discovery.v1`,`webmcp.v1`]),a=e=>{if(!r){if(r=!0,clearTimeout(l),i.removeEventListener(`close`,s),i.removeEventListener(`error`,o),i.removeEventListener(`message`,c),e===null)try{i.close()}catch{}n(e)}},o=()=>{a(null)},s=()=>{a(null)},c=t=>{let n;try{n=JSON.parse(String(t.data))}catch{return}let r=f(n);r&&a({endpoint:{hello:r,host:e.host,port:e.port},socket:i})},l=setTimeout(()=>{a(null)},1200);i.addEventListener(`close`,s,{once:!0}),i.addEventListener(`error`,o,{once:!0}),i.addEventListener(`message`,c)})}function b(e){let t=new Map,r=null,s=null,l=!1,d=null,m=null,b=`idle`,x=0,S=null,C=e=>{for(let[n,r]of t)clearTimeout(r.timeoutId),t.delete(n),r.reject(Error(e))};function w(n,r){let a=i();return new Promise((i,o)=>{let s=setTimeout(()=>{t.delete(a),o(Error(`Host response timeout: ${n}`))},e.requestTimeoutMs);t.set(a,{resolve:i,reject:o,timeoutId:s,responseType:`${n}.response`,errorType:`${n}.error`}),window.parent.postMessage({type:`${n}.request`,requestId:a,...r},e.hostOrigin)})}let T=(t,i)=>{let c=[],u=()=>{d&&(clearTimeout(d),d=null)},h=()=>{o(t,JSON.stringify({type:`tools/list`,tools:c}))};m&&(clearTimeout(m),m=null),r=i,s=t,x=0,l=!1,b=`idle`,t.addEventListener(`message`,s=>{let c;try{c=JSON.parse(String(s.data))}catch(e){console.warn(`[webmcp-relay-widget] Failed to parse relay message:`,e);return}let d=f(c);if(d){r={hello:d,host:i.host,port:i.port};return}if(n(c)&&c.type===`hello/accepted`){u(),l=!0,g(e,i),h();return}let m=p(c);if(m){u(),l=!1,_(e),window.parent.postMessage({type:`webmcp.relay.rejected`,host:i.host,port:i.port,message:m.message,reason:m.reason},e.hostOrigin),console.error(`[webmcp-relay-widget] Relay rejected browser hello:`,m.reason,m.message);try{t.close(1008,m.message)}catch{}return}if(!n(c)||typeof c.type!=`string`)return;let v=c;if(v.type===`ping`){o(t,JSON.stringify({type:`pong`}));return}if(v.type===`reload`){window.parent.postMessage({type:`webmcp.reload`},e.hostOrigin);return}if(v.type!==`invoke`){console.debug(`[webmcp-relay-widget] Ignoring unrecognized message type:`,a(v.type));return}w(`webmcp.tools.invoke`,{toolName:v.toolName,args:n(v.args)?v.args:{}}).then(e=>{o(t,JSON.stringify({type:`result`,callId:v.callId,result:e.result}))}).catch(e=>{o(t,JSON.stringify({type:`result`,callId:v.callId,result:{isError:!0,content:[{type:`text`,text:String(e instanceof Error?e.message:e)}]}}))})}),t.addEventListener(`close`,()=>{s===t&&(l=!1,s=null,u(),C(`WebSocket connection lost`),O())},{once:!0}),t.addEventListener(`error`,e=>{console.warn(`[webmcp-relay-widget] WebSocket error:`,e);try{t.close()}catch(e){console.warn(`[webmcp-relay-widget] Error closing socket after error:`,e)}}),w(`webmcp.tools.list`,{}).then(n=>{c=Array.isArray(n.tools)?n.tools:[],o(t,JSON.stringify({type:`hello`,tabId:e.tabId,origin:e.hostOrigin,title:e.hostTitle||document.referrer||`Unknown page`,url:e.hostUrl})),d=setTimeout(()=>{d=null,!(s!==t||t.readyState!==WebSocket.OPEN||l)&&(console.warn(`[webmcp-relay-widget] Relay did not acknowledge browser hello`),t.close(4e3,`Browser hello was not acknowledged`))},1e3)}).catch(e=>{console.warn(`[webmcp-relay-widget] Hello handshake failed:`,e);try{t.close()}catch{}})},E=async t=>{let n=await y({host:t.host,port:t.port});if(!n)return!1;let r=n.endpoint;return e.relayId&&r.hello.relayId!==e.relayId||e.relayWorkspace&&r.hello.workspace!==e.relayWorkspace?(n.socket.close(),!1):(T(n.socket,r),!0)},D=async()=>{b=`discovering`;try{for(let t of v(e))if(await E(t))return!0;return!1}finally{b===`discovering`&&(b=`idle`)}},O=()=>{if(!r||m)return;let e={host:r.host,port:r.port},t=Math.round(500*(.85+Math.random()*.3));m=setTimeout(()=>{m=null,E(e).then(e=>{e||k()})},t)},k=()=>{if(m)return;let e=c[x];if(e===void 0){M();return}m=setTimeout(()=>{m=null,D().then(e=>{e||(x+=1,k())})},e)},A=()=>{document.visibilityState===`visible`&&b===`dormant`&&P()},j=()=>{document.removeEventListener(`visibilitychange`,A),S!==null&&(clearInterval(S),S=null)},M=()=>{b!==`dormant`&&(b=`dormant`,m&&(clearTimeout(m),m=null),document.addEventListener(`visibilitychange`,A),S=setInterval(()=>{N()},12e4))},N=async()=>{if(b!==`dormant`)return;let t=new Set,n=[],r=(e,r)=>{let i=`${e}:${String(r)}`;t.has(i)||(t.add(i),n.push({host:e,port:r}))};e.relayPortHint!==void 0&&r(e.relayHostHint,e.relayPortHint);let i=h(e);if(i&&r(i.host,i.port),n.length!==0){b=`discovering`,j();for(let e of n)if(await E(e)){x=0;return}M()}},P=()=>{j(),x=0,D().then(e=>{e||M()})};window.addEventListener(`message`,r=>{if(r.source!==window.parent||r.origin!==e.hostOrigin)return;let i=r.data;if(n(i)&&i.type===`webmcp.tools.changed`){s&&l&&o(s,JSON.stringify({type:`tools/changed`,tools:Array.isArray(i.tools)?i.tools:[]}));return}if(n(i)&&i.type===`webmcp.connect`){b===`dormant`?P():!s&&b!==`discovering`&&D();return}let a=u(i);if(!a)return;let c=t.get(a.requestId);if(c){if(a.type===c.responseType){clearTimeout(c.timeoutId),t.delete(a.requestId),c.resolve(a);return}a.type===c.errorType&&(clearTimeout(c.timeoutId),t.delete(a.requestId),c.reject(Error(String(a.error||`Unknown host error`))))}}),e.autoConnect&&D().then(e=>{e||k()})}d()})();
|
|
@@ -49,7 +49,9 @@ const stripLikeC4Comments = (content: string) => content.replace(/\/\*[\s\S]*?\*
|
|
|
49
49
|
const parseLikeC4Views = (content: string, filePath: string): LikeC4View[] => {
|
|
50
50
|
const contentWithoutComments = stripLikeC4Comments(content);
|
|
51
51
|
const viewDeclarationPattern =
|
|
52
|
-
|
|
52
|
+
// `of` names an element, dotted or not (`[\w.-]*` takes the dots: a separate group for each dotted part made the
|
|
53
|
+
// pattern backtrack heavily on a long dotted name without its `{`)
|
|
54
|
+
/\b(?:(dynamic|deployment)\s+)?view(?:\s+([A-Za-z_][\w.-]*))?(?:\s+of\s+[A-Za-z_][\w.-]*)?\s*\{/g;
|
|
53
55
|
const views: LikeC4View[] = [];
|
|
54
56
|
let match: RegExpExecArray | null;
|
|
55
57
|
|
|
@@ -6,12 +6,12 @@ import NavigationProgress from '../components/NavigationProgress.astro';
|
|
|
6
6
|
import config from '@config';
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
|
-
title
|
|
9
|
+
/** The page's own title; the catalog's title follows it (the homepage has none) */
|
|
10
|
+
title?: string;
|
|
10
11
|
description?: string;
|
|
11
|
-
ogTitle?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const { title, description
|
|
14
|
+
const { title, description } = Astro.props;
|
|
15
15
|
const catalogTheme = config.theme || 'default';
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -50,7 +50,7 @@ const catalogTheme = config.theme || 'default';
|
|
|
50
50
|
document.addEventListener('astro:page-load', applyTheme);
|
|
51
51
|
})();
|
|
52
52
|
</script>
|
|
53
|
-
<SEO title={title} description={description}
|
|
53
|
+
<SEO title={title} description={description} />
|
|
54
54
|
<AnalyticsHead />
|
|
55
55
|
<slot name="head" />
|
|
56
56
|
</head>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
|
|
3
3
|
import { buildUrl } from '@utils/url-builder';
|
|
4
|
-
import { Settings, Server, Bot,
|
|
4
|
+
import { Settings, Server, Bot, ScanText, BadgeCheck } from 'lucide-react';
|
|
5
5
|
|
|
6
6
|
export type SettingsSection = 'general' | 'mcp' | 'assistant' | 'llm-access' | 'license';
|
|
7
7
|
|
|
@@ -55,7 +55,7 @@ const groups: SectionGroup[] = [
|
|
|
55
55
|
id: 'llm-access',
|
|
56
56
|
label: 'LLM Access',
|
|
57
57
|
href: buildUrl('/settings/llm-access'),
|
|
58
|
-
icon:
|
|
58
|
+
icon: ScanText,
|
|
59
59
|
},
|
|
60
60
|
],
|
|
61
61
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
interface Props {
|
|
3
|
-
title
|
|
3
|
+
/** The page's own title; the catalog's title follows it (the homepage has none) */
|
|
4
|
+
title?: string;
|
|
4
5
|
sidebar?: boolean;
|
|
5
6
|
description?: string;
|
|
6
7
|
showNestedSideBar?: boolean;
|
|
@@ -430,7 +431,7 @@ const { title, description, showNestedSideBar = true, showHeader = true, reduced
|
|
|
430
431
|
const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/docs', true)];
|
|
431
432
|
---
|
|
432
433
|
|
|
433
|
-
<BaseLayout title={
|
|
434
|
+
<BaseLayout title={title} description={description}>
|
|
434
435
|
<Fragment slot="head">
|
|
435
436
|
<script is:inline define:vars={{ verticalNavAutoCollapsePaths }}>
|
|
436
437
|
(() => {
|
|
@@ -1,358 +1,21 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { buildUrl } from '@utils/url-builder';
|
|
3
|
-
import config from '@config';
|
|
4
|
-
|
|
5
|
-
import { getCollection } from 'astro:content';
|
|
6
2
|
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
7
|
-
import
|
|
3
|
+
import CatalogDashboard from '@components/Homepage/CatalogDashboard.astro';
|
|
8
4
|
|
|
9
5
|
const { showNestedSideBar = true } = Astro.props;
|
|
10
|
-
|
|
11
|
-
// Lightweight data fetch: only raw collections, no hydration.
|
|
12
|
-
const [allDomains, allServices, allEvents, allCommands, allQueries, allFlows] = await Promise.all([
|
|
13
|
-
getCollection('domains'),
|
|
14
|
-
getCollection('services'),
|
|
15
|
-
getCollection('events'),
|
|
16
|
-
getCollection('commands'),
|
|
17
|
-
getCollection('queries'),
|
|
18
|
-
getCollection('flows'),
|
|
19
|
-
]);
|
|
20
|
-
|
|
21
|
-
const isCurrentVersion = (item: { data: { hidden?: boolean }; filePath?: string }) =>
|
|
22
|
-
item.data.hidden !== true && !item.filePath?.includes('versioned');
|
|
23
|
-
|
|
24
|
-
const domains = allDomains.filter(isCurrentVersion);
|
|
25
|
-
const services = allServices.filter(isCurrentVersion);
|
|
26
|
-
const events = allEvents.filter(isCurrentVersion);
|
|
27
|
-
const commands = allCommands.filter(isCurrentVersion);
|
|
28
|
-
const queries = allQueries.filter(isCurrentVersion);
|
|
29
|
-
const messages = [...events, ...commands, ...queries];
|
|
30
|
-
const flows = allFlows.filter(isCurrentVersion);
|
|
31
|
-
|
|
32
|
-
const getDefaultUrl = (route: string, defaultValue: string) => {
|
|
33
|
-
if (domains.length > 0) return buildUrl(`/${route}/domains/${domains[0].data.id}/${domains[0].data.version}`);
|
|
34
|
-
if (services.length > 0) return buildUrl(`/${route}/services/${services[0].data.id}/${services[0].data.version}`);
|
|
35
|
-
if (flows.length > 0) return buildUrl(`/${route}/flows/${flows[0].data.id}/${flows[0].data.version}`);
|
|
36
|
-
return buildUrl(defaultValue);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
interface StatTile {
|
|
40
|
-
label: string;
|
|
41
|
-
count: number;
|
|
42
|
-
href: string;
|
|
43
|
-
emptyHref: string;
|
|
44
|
-
tone: string; // CSS color expression — drives accent rail + count gradient
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const statTiles: StatTile[] = [
|
|
48
|
-
{
|
|
49
|
-
label: 'Domains',
|
|
50
|
-
count: domains.length,
|
|
51
|
-
href: buildUrl('/discover/domains'),
|
|
52
|
-
emptyHref: 'https://www.eventcatalog.dev/docs/domains',
|
|
53
|
-
tone: '250 204 21', // amber-400
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
label: 'Services',
|
|
57
|
-
count: services.length,
|
|
58
|
-
href: buildUrl('/discover/services'),
|
|
59
|
-
emptyHref: 'https://www.eventcatalog.dev/docs/services',
|
|
60
|
-
tone: '244 114 182', // pink-400
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
label: 'Messages',
|
|
64
|
-
count: messages.length,
|
|
65
|
-
href: buildUrl('/discover/events'),
|
|
66
|
-
emptyHref: 'https://www.eventcatalog.dev/docs/messages',
|
|
67
|
-
tone: '167 139 250', // violet-400
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
label: 'Flows',
|
|
71
|
-
count: flows.length,
|
|
72
|
-
href: buildUrl('/discover/flows'),
|
|
73
|
-
emptyHref: 'https://www.eventcatalog.dev/docs/flows',
|
|
74
|
-
tone: '94 234 212', // teal-300
|
|
75
|
-
},
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
interface ExploreCard {
|
|
79
|
-
title: string;
|
|
80
|
-
description: string;
|
|
81
|
-
icon: any;
|
|
82
|
-
href: string;
|
|
83
|
-
external?: boolean;
|
|
84
|
-
/** When true, renders as the lead "feature" card with extra width and CTA styling. */
|
|
85
|
-
feature?: boolean;
|
|
86
|
-
tone: string; // RGB triple for the icon tile
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const exploreCards: ExploreCard[] = [
|
|
90
|
-
{
|
|
91
|
-
title: 'Documentation',
|
|
92
|
-
description: 'Browse every domain, service, message, and flow your teams have published.',
|
|
93
|
-
icon: BookOpenText,
|
|
94
|
-
href: getDefaultUrl('docs', 'domains'),
|
|
95
|
-
feature: true,
|
|
96
|
-
tone: '96 165 250', // blue-400
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
title: 'Visualizer',
|
|
100
|
-
description: 'See how services connect — message flows across your architecture.',
|
|
101
|
-
icon: Workflow,
|
|
102
|
-
href: getDefaultUrl('visualiser', 'domains'),
|
|
103
|
-
tone: '167 139 250', // violet-400
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
title: 'Discover',
|
|
107
|
-
description: 'Search every event, service, agent, and team across the catalog.',
|
|
108
|
-
icon: TableProperties,
|
|
109
|
-
href: buildUrl('/discover/events'),
|
|
110
|
-
tone: '94 234 212', // teal-300
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
title: 'Schema Explorer',
|
|
114
|
-
description: 'Track schema evolution, compare versions, and catch breaking changes.',
|
|
115
|
-
icon: FileJson,
|
|
116
|
-
href: buildUrl('/schemas/explorer'),
|
|
117
|
-
tone: '250 204 21', // amber-400
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
title: 'Team Directory',
|
|
121
|
-
description: 'Find owners, on-call contacts, and the team behind every service.',
|
|
122
|
-
icon: BookUser,
|
|
123
|
-
href: buildUrl('/directory/users'),
|
|
124
|
-
tone: '251 146 60', // orange-400
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
title: 'API & SDK',
|
|
128
|
-
description: 'Programmatic access — query and manage your catalog with a typed SDK.',
|
|
129
|
-
icon: Code2,
|
|
130
|
-
href: 'https://www.eventcatalog.dev/docs/sdk',
|
|
131
|
-
external: true,
|
|
132
|
-
tone: '129 140 248', // indigo-400
|
|
133
|
-
},
|
|
134
|
-
];
|
|
135
6
|
---
|
|
136
7
|
|
|
137
|
-
<VerticalSideBarLayout
|
|
138
|
-
<div class="ec-home
|
|
139
|
-
|
|
140
|
-
<header class="ec-hero">
|
|
141
|
-
<div class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[rgb(var(--ec-accent))]">Catalog</div>
|
|
142
|
-
<div class="mt-3 flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
|
|
143
|
-
<div>
|
|
144
|
-
<h1 class="text-[28px] font-semibold leading-[1.1] tracking-tight text-[rgb(var(--ec-page-text))] md:text-[32px]">
|
|
145
|
-
{config?.organizationName || 'EventCatalog'}
|
|
146
|
-
</h1>
|
|
147
|
-
<p class="mt-2 max-w-2xl text-[14px] leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
148
|
-
{config.tagline || 'Explore and understand your event-driven architecture.'}
|
|
149
|
-
</p>
|
|
150
|
-
</div>
|
|
151
|
-
<div class="flex items-center gap-2">
|
|
152
|
-
<a
|
|
153
|
-
href={getDefaultUrl('docs', 'domains')}
|
|
154
|
-
class="ec-btn-primary inline-flex items-center gap-1.5 rounded-md bg-[rgb(var(--ec-page-bg))] border border-[rgb(var(--ec-page-border))] px-3.5 py-2 text-[12.5px] font-semibold text-[rgb(var(--ec-page-text-muted))] transition-colors hover:border-[rgb(var(--ec-accent)/0.5)] hover:text-[rgb(var(--ec-accent))]"
|
|
155
|
-
>
|
|
156
|
-
Explore Catalog
|
|
157
|
-
<ArrowRight className="h-3.5 w-3.5" />
|
|
158
|
-
</a>
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
</header>
|
|
162
|
-
|
|
163
|
-
<div class="ec-divider"></div>
|
|
164
|
-
|
|
165
|
-
<!-- Stat strip -->
|
|
166
|
-
<section class="ec-stats">
|
|
167
|
-
{
|
|
168
|
-
statTiles.map((tile) => (
|
|
169
|
-
<a
|
|
170
|
-
href={tile.count > 0 ? tile.href : tile.emptyHref}
|
|
171
|
-
target={tile.count === 0 ? '_blank' : undefined}
|
|
172
|
-
rel={tile.count === 0 ? 'noreferrer' : undefined}
|
|
173
|
-
class="ec-stat group"
|
|
174
|
-
style={`--tone: ${tile.tone};`}
|
|
175
|
-
>
|
|
176
|
-
<div class="flex items-baseline justify-between gap-2">
|
|
177
|
-
<span class="text-[11px] font-medium uppercase tracking-[0.14em] text-[rgb(var(--tone))]">{tile.label}</span>
|
|
178
|
-
{tile.count > 0 ? (
|
|
179
|
-
<ArrowUpRight className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))] transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-[rgb(var(--ec-accent))]" />
|
|
180
|
-
) : (
|
|
181
|
-
<Plus className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))] transition-colors group-hover:text-[rgb(var(--ec-accent))]" />
|
|
182
|
-
)}
|
|
183
|
-
</div>
|
|
184
|
-
<div class="mt-3 flex items-baseline gap-2">
|
|
185
|
-
<span class="font-mono text-[34px] font-semibold leading-none tracking-tight text-[rgb(var(--ec-page-text))]">
|
|
186
|
-
{tile.count}
|
|
187
|
-
</span>
|
|
188
|
-
{tile.count === 0 && <span class="text-[12px] text-[rgb(var(--ec-page-text-muted))]">— add some</span>}
|
|
189
|
-
</div>
|
|
190
|
-
</a>
|
|
191
|
-
))
|
|
192
|
-
}
|
|
193
|
-
</section>
|
|
194
|
-
|
|
195
|
-
<!-- Eyebrow + Explore grid -->
|
|
196
|
-
<section class="mt-12">
|
|
197
|
-
<div class="ec-section-eyebrow">
|
|
198
|
-
<span class="text-[11px] font-semibold uppercase tracking-[0.18em] text-[rgb(var(--ec-accent))]">Explore</span>
|
|
199
|
-
<span class="ec-section-rule"></span>
|
|
200
|
-
<span class="font-mono text-[11px] text-[rgb(var(--ec-page-text-muted)/0.7)]">{exploreCards.length} sections</span>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
<div class="ec-explore-grid mt-4">
|
|
204
|
-
{
|
|
205
|
-
exploreCards.map((card) => (
|
|
206
|
-
<a
|
|
207
|
-
href={card.href}
|
|
208
|
-
target={card.external ? '_blank' : undefined}
|
|
209
|
-
rel={card.external ? 'noreferrer' : undefined}
|
|
210
|
-
class:list={['ec-card group', card.feature ? 'ec-card--feature' : '']}
|
|
211
|
-
style={`--tone: ${card.tone};`}
|
|
212
|
-
>
|
|
213
|
-
<div class="flex items-start justify-between gap-3">
|
|
214
|
-
<div class="ec-card-icon">
|
|
215
|
-
<card.icon className="h-4 w-4" />
|
|
216
|
-
</div>
|
|
217
|
-
<ArrowUpRight className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))] transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-[rgb(var(--ec-accent))]" />
|
|
218
|
-
</div>
|
|
219
|
-
<h3 class="mt-4 text-[15px] font-semibold tracking-tight text-[rgb(var(--ec-page-text))]">{card.title}</h3>
|
|
220
|
-
<p class="mt-1.5 text-[13px] leading-relaxed text-[rgb(var(--ec-page-text-muted))]">{card.description}</p>
|
|
221
|
-
</a>
|
|
222
|
-
))
|
|
223
|
-
}
|
|
224
|
-
</div>
|
|
225
|
-
</section>
|
|
8
|
+
<VerticalSideBarLayout showNestedSideBar={showNestedSideBar}>
|
|
9
|
+
<div class="ec-home">
|
|
10
|
+
<CatalogDashboard />
|
|
226
11
|
</div>
|
|
227
12
|
</VerticalSideBarLayout>
|
|
228
13
|
|
|
229
14
|
<style is:global>
|
|
230
15
|
.ec-home {
|
|
231
|
-
/*
|
|
16
|
+
/* The layout pads its content: the homepage sets its own, wider spacing */
|
|
232
17
|
margin-left: calc(var(--ec-app-content-padding-left, 5rem) * -1);
|
|
233
18
|
margin-right: calc(var(--ec-app-content-padding-right, 5rem) * -1);
|
|
234
19
|
padding: 2rem 2rem 0;
|
|
235
20
|
}
|
|
236
|
-
.ec-hero {
|
|
237
|
-
padding-bottom: 1.5rem;
|
|
238
|
-
}
|
|
239
|
-
.ec-divider {
|
|
240
|
-
height: 1px;
|
|
241
|
-
background: linear-gradient(
|
|
242
|
-
to right,
|
|
243
|
-
transparent,
|
|
244
|
-
rgb(var(--ec-page-border)) 12%,
|
|
245
|
-
rgb(var(--ec-page-border)) 88%,
|
|
246
|
-
transparent
|
|
247
|
-
);
|
|
248
|
-
margin: 0.25rem 0 1.5rem;
|
|
249
|
-
}
|
|
250
|
-
.ec-stats {
|
|
251
|
-
display: grid;
|
|
252
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
253
|
-
gap: 0.75rem;
|
|
254
|
-
}
|
|
255
|
-
@media (min-width: 768px) {
|
|
256
|
-
.ec-stats {
|
|
257
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
.ec-stat {
|
|
261
|
-
position: relative;
|
|
262
|
-
display: flex;
|
|
263
|
-
flex-direction: column;
|
|
264
|
-
overflow: hidden;
|
|
265
|
-
border: 1px solid rgb(var(--ec-page-border));
|
|
266
|
-
border-radius: 0.75rem;
|
|
267
|
-
background:
|
|
268
|
-
radial-gradient(80% 100% at 0% 0%, rgb(var(--tone) / 0.05), transparent 60%), rgb(var(--ec-card-bg, var(--ec-page-bg)));
|
|
269
|
-
padding: 1rem 1.1rem 1.1rem;
|
|
270
|
-
transition:
|
|
271
|
-
border-color 200ms,
|
|
272
|
-
transform 200ms,
|
|
273
|
-
box-shadow 200ms;
|
|
274
|
-
text-decoration: none;
|
|
275
|
-
}
|
|
276
|
-
.ec-stat:hover {
|
|
277
|
-
border-color: rgb(var(--ec-accent) / 0.5);
|
|
278
|
-
transform: translateY(-1px);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.ec-section-eyebrow {
|
|
282
|
-
display: flex;
|
|
283
|
-
align-items: center;
|
|
284
|
-
gap: 0.75rem;
|
|
285
|
-
}
|
|
286
|
-
.ec-section-rule {
|
|
287
|
-
flex: 1;
|
|
288
|
-
height: 1px;
|
|
289
|
-
background: linear-gradient(to right, rgb(var(--ec-accent) / 0.4), rgb(var(--ec-page-border)) 30%);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/* Explore grid: bordered cells with breathing room between them. */
|
|
293
|
-
.ec-explore-grid {
|
|
294
|
-
display: grid;
|
|
295
|
-
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
296
|
-
gap: 1rem;
|
|
297
|
-
}
|
|
298
|
-
@media (min-width: 640px) {
|
|
299
|
-
.ec-explore-grid {
|
|
300
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
@media (min-width: 1024px) {
|
|
304
|
-
.ec-explore-grid {
|
|
305
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.ec-card {
|
|
310
|
-
position: relative;
|
|
311
|
-
display: flex;
|
|
312
|
-
flex-direction: column;
|
|
313
|
-
padding: 1.5rem 1.5rem 1.4rem;
|
|
314
|
-
text-decoration: none;
|
|
315
|
-
border: 1px solid rgb(var(--ec-page-border));
|
|
316
|
-
border-radius: 0.875rem;
|
|
317
|
-
background: rgb(var(--ec-card-bg, var(--ec-page-bg)));
|
|
318
|
-
transition:
|
|
319
|
-
background 200ms,
|
|
320
|
-
border-color 200ms;
|
|
321
|
-
min-height: 9.5rem;
|
|
322
|
-
}
|
|
323
|
-
.ec-card:hover {
|
|
324
|
-
background: rgb(var(--ec-page-bg) / 0.4);
|
|
325
|
-
border-color: rgb(var(--ec-accent) / 0.5);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
.ec-card--feature {
|
|
329
|
-
background:
|
|
330
|
-
radial-gradient(60% 90% at 0% 0%, rgb(var(--tone) / 0.07), transparent 60%), rgb(var(--ec-card-bg, var(--ec-page-bg)));
|
|
331
|
-
}
|
|
332
|
-
.ec-card--feature:hover {
|
|
333
|
-
background: radial-gradient(60% 90% at 0% 0%, rgb(var(--ec-accent) / 0.12), transparent 60%), rgb(var(--ec-page-bg) / 0.4);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.ec-card-icon {
|
|
337
|
-
display: inline-flex;
|
|
338
|
-
height: 2.25rem;
|
|
339
|
-
width: 2.25rem;
|
|
340
|
-
align-items: center;
|
|
341
|
-
justify-content: center;
|
|
342
|
-
border-radius: 0.5rem;
|
|
343
|
-
background: rgb(var(--tone) / 0.12);
|
|
344
|
-
color: rgb(var(--tone));
|
|
345
|
-
transition:
|
|
346
|
-
background 200ms,
|
|
347
|
-
color 200ms;
|
|
348
|
-
}
|
|
349
|
-
.ec-card:hover .ec-card-icon {
|
|
350
|
-
background: rgb(var(--ec-accent) / 0.2);
|
|
351
|
-
color: rgb(var(--ec-accent));
|
|
352
|
-
}
|
|
353
|
-
.ec-card--feature .ec-card-icon {
|
|
354
|
-
height: 2.5rem;
|
|
355
|
-
width: 2.5rem;
|
|
356
|
-
border-radius: 0.625rem;
|
|
357
|
-
}
|
|
358
21
|
</style>
|
|
@@ -68,10 +68,9 @@ describe('architecture page redirects', () => {
|
|
|
68
68
|
it('returns not found for resources without an architecture page', async () => {
|
|
69
69
|
mocks.isSSR.mockReturnValue(true);
|
|
70
70
|
|
|
71
|
+
// Nothing found: the page answers with the 404 page
|
|
71
72
|
await expect(
|
|
72
73
|
Page.getData({ params: { type: 'events', id: 'order-created', version: '1.0.0' }, props: {} } as any)
|
|
73
|
-
).
|
|
74
|
-
status: 404,
|
|
75
|
-
});
|
|
74
|
+
).resolves.toBeUndefined();
|
|
76
75
|
});
|
|
77
76
|
});
|
|
@@ -61,11 +61,4 @@ export class Page extends HybridPage {
|
|
|
61
61
|
|
|
62
62
|
return { type, data: { id, name: match.item.data.name, version }, redirectPath: match.redirectPath };
|
|
63
63
|
}
|
|
64
|
-
|
|
65
|
-
protected static createNotFoundResponse(): Response {
|
|
66
|
-
return new Response(null, {
|
|
67
|
-
status: 404,
|
|
68
|
-
statusText: 'Documentation not found',
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
64
|
}
|
|
@@ -9,7 +9,9 @@ import { Page } from './_index.data';
|
|
|
9
9
|
export const prerender = Page.prerender;
|
|
10
10
|
export const getStaticPaths = Page.getStaticPaths;
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const pageData = await Page.getData(Astro);
|
|
13
|
+
if (!pageData) return Astro.rewrite('/404');
|
|
14
|
+
const { data, redirectPath } = pageData;
|
|
13
15
|
const redirectUrl = buildUrl(redirectPath);
|
|
14
16
|
|
|
15
17
|
if (isSSR()) {
|
|
@@ -10,6 +10,7 @@ export const prerender = Page.prerender;
|
|
|
10
10
|
export const getStaticPaths = Page.getStaticPaths;
|
|
11
11
|
|
|
12
12
|
const props = await Page.getData(Astro);
|
|
13
|
+
if (!props) return Astro.rewrite('/404');
|
|
13
14
|
const { Content } = await render(props);
|
|
14
15
|
|
|
15
16
|
const currentVersion = props.data.version;
|
|
@@ -15,6 +15,7 @@ export const prerender = Page.prerender;
|
|
|
15
15
|
export const getStaticPaths = Page.getStaticPaths;
|
|
16
16
|
|
|
17
17
|
const props = await Page.getData(Astro);
|
|
18
|
+
if (!props) return Astro.rewrite('/404');
|
|
18
19
|
const { Content, headings } = await render(props);
|
|
19
20
|
|
|
20
21
|
const pageTitle = `Diagram | ${props.data.name}`;
|
|
@@ -45,6 +45,11 @@ export class Page extends HybridPage {
|
|
|
45
45
|
teams: getTeams,
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
+
// An unknown type (e.g. a mistyped URL) has no directory page
|
|
49
|
+
if (!Object.hasOwn(loaders, type)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
// Get all items of the specified type
|
|
49
54
|
const items = await loaders[type as keyof typeof loaders]();
|
|
50
55
|
|
|
@@ -53,11 +58,4 @@ export class Page extends HybridPage {
|
|
|
53
58
|
data: items,
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
|
-
|
|
57
|
-
protected static createNotFoundResponse(): Response {
|
|
58
|
-
return new Response(null, {
|
|
59
|
-
status: 404,
|
|
60
|
-
statusText: 'Directory type not found',
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
61
|
}
|
|
@@ -7,7 +7,9 @@ import { Page } from './_index.data';
|
|
|
7
7
|
export const prerender = Page.prerender;
|
|
8
8
|
export const getStaticPaths = Page.getStaticPaths;
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const pageData = await Page.getData(Astro);
|
|
11
|
+
if (!pageData) return Astro.rewrite('/404');
|
|
12
|
+
const { type, data } = pageData;
|
|
11
13
|
|
|
12
14
|
function mapToItem(i: any) {
|
|
13
15
|
return {
|
|
@@ -81,6 +81,11 @@ export class Page extends HybridPage {
|
|
|
81
81
|
'data-products': getDataProducts,
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
// An unknown type (e.g. a mistyped URL) has no discover page
|
|
85
|
+
if (!Object.hasOwn(loaders, type)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
// @ts-ignore
|
|
85
90
|
const items = await loaders[type]();
|
|
86
91
|
|
|
@@ -89,11 +94,4 @@ export class Page extends HybridPage {
|
|
|
89
94
|
data: items,
|
|
90
95
|
};
|
|
91
96
|
}
|
|
92
|
-
|
|
93
|
-
protected static createNotFoundResponse(): Response {
|
|
94
|
-
return new Response(null, {
|
|
95
|
-
status: 404,
|
|
96
|
-
statusText: 'Collection type not found',
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
97
|
}
|
|
@@ -27,7 +27,9 @@ import { Page } from './_index.data';
|
|
|
27
27
|
export const prerender = Page.prerender;
|
|
28
28
|
export const getStaticPaths = Page.getStaticPaths;
|
|
29
29
|
|
|
30
|
-
const
|
|
30
|
+
const pageData = await Page.getData(Astro);
|
|
31
|
+
if (!pageData) return Astro.rewrite('/404');
|
|
32
|
+
const { type, data } = pageData;
|
|
31
33
|
|
|
32
34
|
const events = await getEvents();
|
|
33
35
|
const queries = await getQueries();
|