@eventcatalog/core 4.10.12 → 4.10.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-S4LLGOO4.js → chunk-34RMFKFB.js} +1 -1
  6. package/dist/{chunk-Y5XU3YLT.js → chunk-IIECZFXN.js} +1 -1
  7. package/dist/{chunk-VFSEVDCQ.js → chunk-JHUICVBT.js} +1 -1
  8. package/dist/{chunk-A53VCEEA.js → chunk-PADMH2RJ.js} +1 -1
  9. package/dist/{chunk-7URQ754Q.js → chunk-SSSN5FXC.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.js +5 -5
  14. package/dist/generate.cjs +1 -1
  15. package/dist/generate.js +3 -3
  16. package/dist/utils/cli-logger.cjs +1 -1
  17. package/dist/utils/cli-logger.js +2 -2
  18. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +208 -119
  19. package/eventcatalog/src/components/ChatPanel/ChatPanelButton.tsx +28 -8
  20. package/eventcatalog/src/components/ChatPanel/OfflineReply.tsx +45 -0
  21. package/eventcatalog/src/components/Header.astro +11 -6
  22. package/eventcatalog/src/components/MDX/Design/Design.astro +2 -2
  23. package/eventcatalog/src/components/MDX/EntityMap/EntityMap.astro +2 -2
  24. package/eventcatalog/src/components/MDX/Flow/Flow.astro +2 -2
  25. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +2 -2
  26. package/eventcatalog/src/components/Search/Search.astro +11 -4
  27. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +29 -24
  28. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +3 -3
  29. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +2 -2
  30. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +5 -3
  31. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +10 -4
  32. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +2 -2
  33. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +3 -3
  34. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +2 -2
  35. package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -2
  36. package/eventcatalog/src/utils/feature.ts +1 -0
  37. package/package.json +1 -1
@@ -1,9 +1,15 @@
1
- import { useState, useEffect } from 'react';
2
- import { BookOpen } from 'lucide-react';
1
+ import { useState, useEffect, useRef, useCallback } from 'react';
2
+ import { Sparkles } from 'lucide-react';
3
3
  import ChatPanel from './ChatPanel';
4
4
 
5
- const ChatPanelButton = () => {
5
+ const ChatPanelButton = ({ configured = false }: { configured?: boolean }) => {
6
6
  const [isOpen, setIsOpen] = useState(false);
7
+ const buttonRef = useRef<HTMLButtonElement>(null);
8
+ const closePanel = useCallback(() => {
9
+ setIsOpen(false);
10
+ buttonRef.current?.focus();
11
+ }, []);
12
+ const [shortcut, setShortcut] = useState('⌘I');
7
13
 
8
14
  // Listen for custom event to open chat panel from other components
9
15
  useEffect(() => {
@@ -11,22 +17,36 @@ const ChatPanelButton = () => {
11
17
  setIsOpen(true);
12
18
  };
13
19
 
20
+ setShortcut(/Mac|iPhone|iPad/.test(navigator.platform) ? '⌘I' : 'Ctrl I');
21
+ const handleShortcut = (event: KeyboardEvent) => {
22
+ if ((event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey && event.key.toLowerCase() === 'i') {
23
+ event.preventDefault();
24
+ setIsOpen(true);
25
+ }
26
+ };
27
+ window.addEventListener('keydown', handleShortcut);
14
28
  window.addEventListener('eventcatalog:open-chat', handleOpenChat);
15
- return () => window.removeEventListener('eventcatalog:open-chat', handleOpenChat);
29
+ return () => {
30
+ window.removeEventListener('keydown', handleShortcut);
31
+ window.removeEventListener('eventcatalog:open-chat', handleOpenChat);
32
+ };
16
33
  }, []);
17
34
 
18
35
  return (
19
36
  <>
20
37
  <button
38
+ ref={buttonRef}
21
39
  onClick={() => setIsOpen(true)}
22
- className="flex items-center gap-1.5 px-4 py-1.5 rounded-md bg-[rgb(var(--ec-card-bg))] hover:bg-[rgb(var(--ec-content-hover))] ring-1 ring-inset ring-[rgb(var(--ec-page-border))] shadow-xs transition-colors text-sm ml-[-1px]"
40
+ className="flex h-9 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-4 rounded-md bg-[rgb(var(--ec-card-bg))] hover:bg-[rgb(var(--ec-content-hover))] ring-1 ring-inset ring-[rgb(var(--ec-page-border))] shadow-xs transition-colors text-sm"
23
41
  aria-label="Open AI Assistant"
42
+ aria-keyshortcuts="Meta+i Control+i"
43
+ title={`Open Event Catalog Assistant (${shortcut})`}
24
44
  >
25
- <BookOpen size={14} className="text-[rgb(var(--ec-accent))]" />
26
- <span className="font-light text-[rgb(var(--ec-page-text-muted))]">Ask</span>
45
+ <Sparkles size={16} className="shrink-0 text-gray-500" aria-hidden="true" />
46
+ <span className="font-light text-gray-500">Ask</span>
27
47
  </button>
28
48
 
29
- <ChatPanel isOpen={isOpen} onClose={() => setIsOpen(false)} />
49
+ <ChatPanel configured={configured} isOpen={isOpen} onClose={closePanel} />
30
50
  </>
31
51
  );
32
52
  };
@@ -0,0 +1,45 @@
1
+ import { ArrowUpRight } from 'lucide-react';
2
+ import { buildUrl } from '@utils/url-builder';
3
+
4
+ const setupUrl = 'https://www.eventcatalog.dev/docs/development/ask-your-architecture/eventcatalog-assistant/configuration';
5
+ const introduction = 'Your whole catalog, connected to your AI.';
6
+ const description =
7
+ 'Bring your own model and I can help you understand your services, trace how events flow, and explore the impact of a change across your whole catalog.';
8
+ const privacy = 'You choose where your data is processed: on your own infrastructure or with a model provider you trust.';
9
+ const setup = 'I’m not connected to a model yet. Your catalog owner can connect one to get started.';
10
+
11
+ export const offlineReplyText = `${introduction}\n\n${description}\n\n${privacy}\n\n${setup}`;
12
+
13
+ export default function OfflineReply() {
14
+ return (
15
+ <div className="ec-chat-offline w-full space-y-4 py-2 text-[13px] leading-relaxed text-[rgb(var(--ec-content-text))]">
16
+ <div className="space-y-2">
17
+ <p className="text-base font-medium leading-snug text-[rgb(var(--ec-page-text))]">{introduction}</p>
18
+ <p>{description}</p>
19
+ </div>
20
+ <div className="space-y-3 rounded-xl border border-[rgb(var(--ec-accent)/0.15)] bg-[rgb(var(--ec-accent)/0.04)] p-4">
21
+ <div className="space-y-1">
22
+ <p className="font-medium text-[rgb(var(--ec-page-text))]">Your model. Your control.</p>
23
+ <p className="text-[rgb(var(--ec-page-text-muted))]">{privacy}</p>
24
+ </div>
25
+ <p>{setup}</p>
26
+ <a
27
+ href={setupUrl}
28
+ target="_blank"
29
+ rel="noreferrer"
30
+ className="inline-flex items-center gap-2 rounded-lg bg-[rgb(var(--ec-accent))] px-3 py-2 text-xs font-medium text-white transition-colors hover:bg-[rgb(var(--ec-accent-hover))] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[rgb(var(--ec-accent))]"
31
+ >
32
+ Connect your model
33
+ <ArrowUpRight size={14} aria-hidden="true" />
34
+ </a>
35
+ </div>
36
+ <p className="text-xs leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
37
+ Don’t need the assistant?{' '}
38
+ <a href={buildUrl('/settings/assistant')} className="underline underline-offset-2 hover:text-[rgb(var(--ec-page-text))]">
39
+ Turn off Event Catalog Assistant
40
+ </a>{' '}
41
+ or set <code className="text-[11px]">chat.enabled: false</code> in your catalog configuration.
42
+ </p>
43
+ </div>
44
+ );
45
+ }
@@ -2,7 +2,12 @@
2
2
  import catalog from '@utils/eventcatalog-config/catalog';
3
3
  import Search from '@components/Search/Search.astro';
4
4
  import { buildUrl } from '@utils/url-builder';
5
- import { showEventCatalogBranding, showCustomBranding, isEventCatalogChatEnabled } from '@utils/feature';
5
+ import {
6
+ showEventCatalogBranding,
7
+ showCustomBranding,
8
+ isEventCatalogChatVisible,
9
+ isEventCatalogChatEnabled,
10
+ } from '@utils/feature';
6
11
  import { getSession } from 'auth-astro/server';
7
12
  import { isAuthEnabled, isSSR } from '@utils/feature';
8
13
  import { EnvironmentDropdown } from './EnvironmentDropdown';
@@ -33,15 +38,15 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
33
38
  : 'left: var(--ec-vertical-nav-width, 14rem);'}
34
39
  >
35
40
  <div class="px-6">
36
- <div class="flex justify-between items-center">
37
- <div class="hidden lg:flex flex-grow items-center">
38
- <div class="w-full max-w-xl">
41
+ <div class="flex justify-between items-center gap-4">
42
+ <div class="flex min-w-0 flex-1 items-center gap-3">
43
+ <div class="hidden lg:block min-w-0 flex-1 max-w-xl">
39
44
  <Search />
40
45
  </div>
41
- {isEventCatalogChatEnabled() && <ChatPanelButton client:idle />}
46
+ {isEventCatalogChatVisible() && <ChatPanelButton configured={isEventCatalogChatEnabled()} client:idle />}
42
47
  </div>
43
48
 
44
- <div class="hidden md:block w-3/12">
49
+ <div class="hidden md:block shrink-0 ml-auto">
45
50
  {
46
51
  session ? (
47
52
  <div class="flex items-center space-x-4 justify-end pr-2">
@@ -7,10 +7,10 @@ import AstroNodeGraph from '../NodeGraph/AstroNodeGraph';
7
7
  // Visualiser styles ship in the page head so ClientRouter navigations keep them (see NodeGraph.astro).
8
8
  import '@eventcatalog/visualiser/styles-core.css';
9
9
 
10
- import { isVisualiserEnabled, isEventCatalogChatEnabled, isDevMode } from '@utils/feature';
10
+ import { isVisualiserEnabled, isEventCatalogChatVisible, isDevMode } from '@utils/feature';
11
11
  import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
12
12
 
13
- const isChatEnabled = isEventCatalogChatEnabled();
13
+ const isChatEnabled = isEventCatalogChatVisible();
14
14
 
15
15
  let design: any;
16
16
  let id = 'design';
@@ -7,10 +7,10 @@ import AstroNodeGraph from '../NodeGraph/AstroNodeGraph';
7
7
  import '@eventcatalog/visualiser/styles-core.css';
8
8
  import { getVersionFromCollection } from '@utils/collections/versions';
9
9
  import { getServices } from '@utils/collections/services';
10
- import { isEventCatalogChatEnabled, isDevMode } from '@utils/feature';
10
+ import { isEventCatalogChatVisible, isDevMode } from '@utils/feature';
11
11
  import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
12
12
 
13
- const isChatEnabled = isEventCatalogChatEnabled();
13
+ const isChatEnabled = isEventCatalogChatVisible();
14
14
 
15
15
  const { id, version = 'latest', maxHeight, includeKey = true, entities, collection = 'domains', ...rest } = Astro.props;
16
16
  let resource = null;
@@ -6,12 +6,12 @@ import AstroNodeGraph from '../NodeGraph/AstroNodeGraph';
6
6
  // Visualiser styles ship in the page head so ClientRouter navigations keep them (see NodeGraph.astro).
7
7
  import '@eventcatalog/visualiser/styles-core.css';
8
8
  import { getVersionFromCollection } from '@utils/collections/versions';
9
- import { isVisualiserEnabled, isEventCatalogChatEnabled, isDevMode } from '@utils/feature';
9
+ import { isVisualiserEnabled, isEventCatalogChatVisible, isDevMode } from '@utils/feature';
10
10
  import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
11
11
  import { randomUUID } from 'node:crypto';
12
12
  import { parseMdxBooleanProp } from '@utils/markdown';
13
13
 
14
- const isChatEnabled = isEventCatalogChatEnabled();
14
+ const isChatEnabled = isEventCatalogChatVisible();
15
15
 
16
16
  const { id, version = 'latest', maxHeight, mode = 'simple' } = Astro.props;
17
17
  const includeKey = parseMdxBooleanProp(Astro.props.legend ?? Astro.props.includeKey, true);
@@ -29,11 +29,11 @@ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
29
29
  import { getNodesAndEdges as getNodesAndEdgesForContainer } from '@utils/node-graphs/container-node-graph';
30
30
  import { getNodesAndEdges as getNodesAndEdgesForChannel } from '@utils/node-graphs/channel-node-graph';
31
31
  import config from '@config';
32
- import { isEventCatalogChatEnabled, isDevMode } from '@utils/feature';
32
+ import { isEventCatalogChatVisible, isDevMode } from '@utils/feature';
33
33
  import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
34
34
  import { compactVisualiserGraph } from '@utils/node-graphs/compact-visualiser-graph';
35
35
 
36
- const isChatEnabled = isEventCatalogChatEnabled();
36
+ const isChatEnabled = isEventCatalogChatVisible();
37
37
 
38
38
  interface Props {
39
39
  id: string;
@@ -4,18 +4,25 @@ import SearchModal from './SearchModal.tsx';
4
4
  ---
5
5
 
6
6
  <div>
7
- <div class="relative flex items-center w-full pr-4 ml-1">
7
+ <div class="relative flex min-w-0 items-center w-full">
8
8
  <input
9
9
  id="search-dummy-input"
10
10
  type="text"
11
11
  name="search"
12
12
  placeholder="Search EventCatalog"
13
13
  autocomplete="off"
14
- class="block w-full rounded-md caret-transparent border-0 py-1.5 pr-14 pl-10! text-[rgb(var(--ec-header-text))] bg-[rgb(var(--ec-header-bg))] shadow-xs ring-1 ring-inset ring-[rgb(var(--ec-dropdown-border))] placeholder:text-[rgb(var(--ec-icon-color))] font-light sm:text-sm sm:leading-6"
14
+ class="block h-9 min-w-0 w-full rounded-md caret-transparent border-0 py-1.5 pr-20 pl-10! text-[rgb(var(--ec-header-text))] bg-[rgb(var(--ec-header-bg))] shadow-xs ring-1 ring-inset ring-[rgb(var(--ec-dropdown-border))] placeholder:text-gray-400 font-light sm:text-sm sm:leading-6"
15
15
  />
16
16
  <MagnifyingGlassIcon className="absolute inset-y-0 left-0 h-9 w-8 flex items-center pl-4 text-[rgb(var(--ec-icon-color))]" />
17
- <div class="absolute inset-y-0 right-0 flex py-1.5 pr-6">
18
- <kbd class="inline-flex items-center rounded px-1 font-sans text-xs text-[rgb(var(--ec-icon-color))]">⌘K</kbd>
17
+ <div class="absolute inset-y-0 right-0 flex items-center gap-1 pr-2 pointer-events-none">
18
+ <kbd
19
+ class="inline-flex h-6 min-w-6 items-center justify-center rounded-lg border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-card-bg))] px-1 font-sans text-xs font-normal text-[rgb(var(--ec-icon-color))] shadow-xs"
20
+ >⌘</kbd
21
+ >
22
+ <kbd
23
+ class="inline-flex h-6 min-w-6 items-center justify-center rounded-lg border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-card-bg))] px-1 font-sans text-xs font-normal text-[rgb(var(--ec-icon-color))] shadow-xs"
24
+ >K</kbd
25
+ >
19
26
  </div>
20
27
  </div>
21
28
  </div>
@@ -76,34 +76,39 @@ export const AssistantSettingsForm = ({ canEdit, initial, chatAvailable, hasPlan
76
76
  <Row
77
77
  title="Assistant Agent"
78
78
  description="Assistant agent that answers questions about your architecture directly in your catalog."
79
- canEdit={canEdit && chatAvailable}
79
+ canEdit={canEdit}
80
80
  dirty={dirty}
81
81
  saving={saving}
82
- onSave={chatAvailable ? save : undefined}
82
+ onSave={save}
83
83
  >
84
- {chatAvailable ? (
85
- <div className="space-y-3">
86
- <ToggleRow
87
- icon={<MessageSquare className="h-4 w-4" aria-hidden />}
88
- label={chatEnabled ? 'Enabled' : 'Disabled'}
89
- hint={chatEnabled ? 'Chat is available to readers of this catalog.' : 'Chat is hidden from the catalog.'}
90
- checked={chatEnabled}
91
- disabled={!canEdit}
92
- onChange={setChatEnabled}
93
- />
94
- {chatEnabled && <ConfigurationRequired />}
95
- </div>
96
- ) : !hasPlan ? (
97
- <UpgradeRequired
98
- tier="Starter and Scale"
99
- blurb="The EventCatalog Assistant is part of our paid plans. Upgrade to give your team a built-in AI agent that answers questions about your architecture."
100
- docsUrl={ASSISTANT_DOCS_URL}
84
+ <div className="space-y-3">
85
+ <ToggleRow
86
+ icon={<MessageSquare className="h-4 w-4" aria-hidden />}
87
+ label={chatEnabled ? 'Enabled' : 'Disabled'}
88
+ hint={
89
+ chatEnabled
90
+ ? 'Event Catalog Assistant is visible in this catalog.'
91
+ : 'Event Catalog Assistant is hidden from this catalog.'
92
+ }
93
+ checked={chatEnabled}
94
+ disabled={!canEdit}
95
+ onChange={setChatEnabled}
101
96
  />
102
- ) : !inSSR ? (
103
- <AssistantNeedsSSR />
104
- ) : !hasChatConfigFile ? (
105
- <AssistantNeedsConfigFile />
106
- ) : null}
97
+ {chatEnabled &&
98
+ (chatAvailable ? (
99
+ <ConfigurationRequired />
100
+ ) : !hasPlan ? (
101
+ <UpgradeRequired
102
+ tier="Starter and Scale"
103
+ blurb="The EventCatalog Assistant is part of our paid plans. Upgrade to give your team a built-in AI agent that answers questions about your architecture."
104
+ docsUrl={ASSISTANT_DOCS_URL}
105
+ />
106
+ ) : !inSSR ? (
107
+ <AssistantNeedsSSR />
108
+ ) : !hasChatConfigFile ? (
109
+ <AssistantNeedsConfigFile />
110
+ ) : null)}
111
+ </div>
107
112
  </Row>
108
113
  </form>
109
114
  );
@@ -21,7 +21,7 @@ import {
21
21
  isVisualiserEnabled,
22
22
  isMarkdownDownloadEnabled,
23
23
  isRSSEnabled,
24
- isEventCatalogChatEnabled,
24
+ isEventCatalogChatVisible,
25
25
  isArchitectureGraphEnabled,
26
26
  } from '@utils/feature';
27
27
 
@@ -152,11 +152,11 @@ const editUrl =
152
152
  client:only="react"
153
153
  variant="toolbar"
154
154
  schemas={[]}
155
- chatEnabled={isEventCatalogChatEnabled()}
155
+ chatEnabled={isEventCatalogChatVisible()}
156
156
  markdownDownloadEnabled={isMarkdownDownloadEnabled()}
157
157
  rssFeedEnabled={isRSSEnabled()}
158
158
  editUrl={editUrl}
159
- preferChatAsDefault={isEventCatalogChatEnabled()}
159
+ preferChatAsDefault={isEventCatalogChatVisible()}
160
160
  />
161
161
  </div>
162
162
  </div>
@@ -7,7 +7,7 @@ import config from '@config';
7
7
  import { buildUrl } from '@utils/url-builder';
8
8
  import { GitCompare, X, AlignLeft, HistoryIcon } from 'lucide-react';
9
9
  import CopyAsMarkdown from '@components/CopyAsMarkdown';
10
- import { isLLMSTxtEnabled, isEventCatalogChatEnabled } from '@utils/feature';
10
+ import { isLLMSTxtEnabled, isEventCatalogChatVisible } from '@utils/feature';
11
11
 
12
12
  import { Page } from './_index.data';
13
13
 
@@ -21,7 +21,7 @@ const pageTitle = `Diagram | ${props.data.name}`;
21
21
  const currentVersion = props.data.version;
22
22
  const allVersions = props.allVersions || [currentVersion];
23
23
  const hasMultipleVersions = allVersions.length > 1;
24
- const chatEnabled = isEventCatalogChatEnabled();
24
+ const chatEnabled = isEventCatalogChatVisible();
25
25
  const markdownDownloadEnabled = isLLMSTxtEnabled();
26
26
  const chatQuery = `Tell me about the "${props.data.name}" diagram (version ${props.data.version})`;
27
27
  ---
@@ -8,7 +8,7 @@ import CopyAsMarkdown from '@components/CopyAsMarkdown';
8
8
  import Badge from '@components/Badge.astro';
9
9
  import { buildUrl } from '@utils/url-builder';
10
10
  import { AlignLeftIcon, HistoryIcon } from 'lucide-react';
11
- import { isEventCatalogChatEnabled, isMarkdownDownloadEnabled, isResourceDocsEnabled } from '@utils/feature';
11
+ import { isEventCatalogChatVisible, isMarkdownDownloadEnabled, isResourceDocsEnabled } from '@utils/feature';
12
12
  import { getResourceDocTypeLabel } from '@utils/collections/resource-docs';
13
13
  import { getIcon } from '@utils/badges';
14
14
  import { collectionToResourceMap } from '@utils/collections/util';
@@ -37,7 +37,7 @@ const docsBasePath = `/docs/${props.data.resourceCollection}/${props.data.resour
37
37
  const singularResourceName =
38
38
  collectionToResourceMap[props.data.resourceCollection as keyof typeof collectionToResourceMap] ??
39
39
  props.data.resourceCollection.slice(0, props.data.resourceCollection.length - 1);
40
- const chatEnabled = isEventCatalogChatEnabled();
40
+ const chatEnabled = isEventCatalogChatVisible();
41
41
  const chatQuery = `Tell me about the ${props.data.type} doc "${title}" for ${props.data.resourceId} (version ${props.data.version})`;
42
42
 
43
43
  const pagefindAttributes =
@@ -69,7 +69,9 @@ const pagefindAttributes =
69
69
  {
70
70
  badges.length > 0 && (
71
71
  <div class="flex flex-wrap gap-1.5 pt-4">
72
- {badges.map((badge: any) => <Badge badge={badge} />)}
72
+ {badges.map((badge: any) => (
73
+ <Badge badge={badge} />
74
+ ))}
73
75
  </div>
74
76
  )
75
77
  }
@@ -8,7 +8,7 @@ import CopyAsMarkdown from '@components/CopyAsMarkdown';
8
8
  import Badge from '@components/Badge.astro';
9
9
  import { buildUrl } from '@utils/url-builder';
10
10
  import { AlignLeftIcon, HistoryIcon } from 'lucide-react';
11
- import { isEventCatalogChatEnabled, isMarkdownDownloadEnabled, isResourceDocsEnabled } from '@utils/feature';
11
+ import { isEventCatalogChatVisible, isMarkdownDownloadEnabled, isResourceDocsEnabled } from '@utils/feature';
12
12
  import { getIcon } from '@utils/badges';
13
13
  import { collectionToResourceMap } from '@utils/collections/util';
14
14
  import { getResourceDocTypeLabel } from '@utils/collections/resource-docs';
@@ -38,7 +38,7 @@ const singularResourceName =
38
38
  collectionToResourceMap[props.data.resourceCollection as keyof typeof collectionToResourceMap] ??
39
39
  props.data.resourceCollection.slice(0, props.data.resourceCollection.length - 1);
40
40
  const typeLabel = getResourceDocTypeLabel(props.data.type);
41
- const chatEnabled = isEventCatalogChatEnabled();
41
+ const chatEnabled = isEventCatalogChatVisible();
42
42
  const chatQuery = `Tell me about the ${props.data.type} doc "${title}" for ${props.data.resourceId} (version ${props.data.version})`;
43
43
 
44
44
  const pagefindAttributes =
@@ -60,11 +60,17 @@ const pagefindAttributes =
60
60
  <span class="text-xs md:text-sm font-semibold text-[rgb(var(--ec-accent))] capitalize">{typeLabel}</span>
61
61
  <h2 id="doc-page-header" class="text-2xl md:text-4xl font-bold text-[rgb(var(--ec-page-text))]">{title}</h2>
62
62
  </div>
63
- {props.data.summary && <p class="text-base pt-4 text-[rgb(var(--ec-page-text-muted))] font-light">{props.data.summary}</p>}
63
+ {
64
+ props.data.summary && (
65
+ <p class="text-base pt-4 text-[rgb(var(--ec-page-text-muted))] font-light">{props.data.summary}</p>
66
+ )
67
+ }
64
68
  {
65
69
  badges.length > 0 && (
66
70
  <div class="flex flex-wrap gap-1.5 pt-4">
67
- {badges.map((badge: any) => <Badge badge={badge} />)}
71
+ {badges.map((badge: any) => (
72
+ <Badge badge={badge} />
73
+ ))}
68
74
  </div>
69
75
  )
70
76
  }
@@ -12,7 +12,7 @@ import js from '@asyncapi/react-component/browser/standalone/without-parser.js?u
12
12
  import { AsyncApiComponentWP, type ConfigInterface } from '@asyncapi/react-component';
13
13
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
14
14
  import CopyAsMarkdown from '@components/CopyAsMarkdown';
15
- import { isEventCatalogChatEnabled } from '@utils/feature';
15
+ import { isEventCatalogChatVisible } from '@utils/feature';
16
16
  import Config from '@utils/eventcatalog-config/catalog';
17
17
  import { Page } from './_[filename].data';
18
18
  import { getAbsoluteFilePathForAstroFile } from '@utils/files';
@@ -148,7 +148,7 @@ const renderedComponent = renderToString(component);
148
148
  const pageTitle = `${collection} | ${data.name} | AsyncApi Spec`.replace(/^\w/, (c) => c.toUpperCase());
149
149
 
150
150
  // Chat configuration
151
- const chatEnabled = isEventCatalogChatEnabled();
151
+ const chatEnabled = isEventCatalogChatVisible();
152
152
  const chatQuery = `Tell me about the AsyncAPI specification for "${data.name}" (version ${data.version})`;
153
153
 
154
154
  // Index only the latest version
@@ -61,7 +61,7 @@ import { getIcon } from '@utils/badges';
61
61
  import { buildUrl, buildEditUrlForResource } from '@utils/url-builder';
62
62
  import { isIconPath, resolveIconUrl } from '@utils/icon';
63
63
  import {
64
- isEventCatalogChatEnabled,
64
+ isEventCatalogChatVisible,
65
65
  isMarkdownDownloadEnabled,
66
66
  isVisualiserEnabled,
67
67
  isRSSEnabled,
@@ -479,11 +479,11 @@ if (!isAdrPage && !hasCurrentFlowEmbed && !hasCurrentPageNodeGraph) {
479
479
  variant="toolbar"
480
480
  schemas={schemasForResource}
481
481
  chatQuery={generatePromptForResource(props)}
482
- chatEnabled={isEventCatalogChatEnabled()}
482
+ chatEnabled={isEventCatalogChatVisible()}
483
483
  markdownDownloadEnabled={isMarkdownDownloadEnabled()}
484
484
  rssFeedEnabled={isRSSEnabled()}
485
485
  editUrl={editUrl}
486
- preferChatAsDefault={isEventCatalogChatEnabled()}
486
+ preferChatAsDefault={isEventCatalogChatVisible()}
487
487
  mcpServerUrl={mcpServerUrl}
488
488
  resourceName={props.data.name}
489
489
  mcpResourceType={mcpResourceType}
@@ -5,7 +5,7 @@ import OpenAPISpec from './_OpenAPI.tsx';
5
5
  import { DocumentMinusIcon } from '@heroicons/react/24/outline';
6
6
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
7
7
  import CopyAsMarkdown from '@components/CopyAsMarkdown';
8
- import { isEventCatalogChatEnabled } from '@utils/feature';
8
+ import { isEventCatalogChatVisible } from '@utils/feature';
9
9
  import './_styles.css';
10
10
  import { Page } from './_[filename].data.ts';
11
11
  import { getAbsoluteFilePathForAstroFile } from '@utils/files';
@@ -31,7 +31,7 @@ let content = '';
31
31
  const pageTitle = `${collection} | ${data.name} | OpenAPI Spec`.replace(/^\w/, (c) => c.toUpperCase());
32
32
 
33
33
  // Chat configuration
34
- const chatEnabled = isEventCatalogChatEnabled();
34
+ const chatEnabled = isEventCatalogChatVisible();
35
35
  const chatQuery = `Tell me about the OpenAPI specification for "${data.name}" (version ${data.version})`;
36
36
 
37
37
  // Index only the latest version
@@ -4,11 +4,11 @@ import AstroNodeGraph from '@components/MDX/NodeGraph/AstroNodeGraph';
4
4
  import '@eventcatalog/visualiser/styles-core.css';
5
5
  import { ClientRouter } from 'astro:transitions';
6
6
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
7
- import { isEventCatalogChatEnabled } from '@utils/feature';
7
+ import { isEventCatalogChatVisible } from '@utils/feature';
8
8
 
9
9
  import { Page } from './_index.data';
10
10
 
11
- const isChatEnabled = isEventCatalogChatEnabled();
11
+ const isChatEnabled = isEventCatalogChatVisible();
12
12
 
13
13
  export const prerender = Page.prerender;
14
14
  export const getStaticPaths = Page.getStaticPaths;
@@ -1,6 +1,7 @@
1
1
  import config from '../../eventcatalog.config.js';
2
2
 
3
3
  // Open-source feature flags
4
+ export const isEventCatalogChatVisible = () => config?.chat?.enabled ?? true;
4
5
  export const isSSR = () => config?.output === 'server';
5
6
  export const isVisualiserEnabled = () => config?.visualiser?.enabled ?? true;
6
7
  // Opt-in while in beta — building the whole-catalog graph is unproven on very large catalogs
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "4.10.12",
10
+ "version": "4.10.13",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },