@eventcatalog/core 2.37.0 → 2.37.2
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/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-B6ZIYCJG.js → chunk-7J7J25A5.js} +1 -1
- package/dist/{chunk-5OMFLY4U.js → chunk-ARZJXJW7.js} +1 -1
- package/dist/{chunk-NJTCGQQ5.js → chunk-BXWTM2JX.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +3 -3
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +194 -0
- package/eventcatalog/src/components/SideBars/MessageSideBar.astro +2 -1
- package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.client.tsx +20 -1
- package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.server.tsx +13 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +34 -7
- package/eventcatalog/src/pages/index.astro +4 -2
- package/eventcatalog/src/utils/collections/schemas.ts +60 -0
- package/eventcatalog/src/utils/feature.ts +8 -1
- package/package.json +2 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-ARZJXJW7.js";
|
|
4
|
+
import "../chunk-7J7J25A5.js";
|
|
5
|
+
import "../chunk-BXWTM2JX.js";
|
|
6
6
|
import "../chunk-E7TXTI7G.js";
|
|
7
7
|
export {
|
|
8
8
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
package/dist/eventcatalog.js
CHANGED
|
@@ -6,15 +6,15 @@ import {
|
|
|
6
6
|
} from "./chunk-DCLTVJDP.js";
|
|
7
7
|
import {
|
|
8
8
|
log_build_default
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-ARZJXJW7.js";
|
|
10
|
+
import "./chunk-7J7J25A5.js";
|
|
11
11
|
import {
|
|
12
12
|
catalogToAstro,
|
|
13
13
|
checkAndConvertMdToMdx
|
|
14
14
|
} from "./chunk-SLEMYHTU.js";
|
|
15
15
|
import {
|
|
16
16
|
VERSION
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BXWTM2JX.js";
|
|
18
18
|
import {
|
|
19
19
|
isBackstagePluginEnabled,
|
|
20
20
|
isEventCatalogScaleEnabled,
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Button } from '@headlessui/react';
|
|
2
|
+
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
3
|
+
import { Copy, FileText, MessageCircleQuestion, ChevronDownIcon, ExternalLink } from 'lucide-react';
|
|
4
|
+
import React, { useState, isValidElement } from 'react';
|
|
5
|
+
import type { Schema } from '@utils/collections/schemas';
|
|
6
|
+
import { buildUrl } from '@utils/url-builder';
|
|
7
|
+
|
|
8
|
+
// Type allows either a component type (like Lucide icon) or a pre-rendered element (like <img>)
|
|
9
|
+
type IconInput = React.ElementType | React.ReactElement;
|
|
10
|
+
|
|
11
|
+
// Helper component for menu items
|
|
12
|
+
const MenuItemContent = ({
|
|
13
|
+
icon: iconProp,
|
|
14
|
+
title,
|
|
15
|
+
description,
|
|
16
|
+
external = false,
|
|
17
|
+
}: {
|
|
18
|
+
icon: IconInput;
|
|
19
|
+
title: string;
|
|
20
|
+
description: string;
|
|
21
|
+
external?: boolean;
|
|
22
|
+
}) => {
|
|
23
|
+
let iconElement: React.ReactNode;
|
|
24
|
+
|
|
25
|
+
if (isValidElement(iconProp)) {
|
|
26
|
+
// It's already a React element (e.g., <img>), render it directly
|
|
27
|
+
iconElement = iconProp;
|
|
28
|
+
} else {
|
|
29
|
+
// It must be an ElementType (component constructor like Lucide icon)
|
|
30
|
+
const IconComponent = iconProp as React.ElementType;
|
|
31
|
+
iconElement = <IconComponent className="w-5 h-5 text-gray-500" />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex items-center gap-3 px-3 py-2 text-sm">
|
|
36
|
+
<div className="p-1 border border-gray-200 rounded">{iconElement}</div>
|
|
37
|
+
<div className="flex-1">
|
|
38
|
+
<div className="font-medium text-gray-800">{title}</div>
|
|
39
|
+
<div className="text-xs text-gray-500">{description}</div>
|
|
40
|
+
</div>
|
|
41
|
+
{external && <ExternalLink className="w-4 h-4 text-gray-400" />}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export function CopyPageMenu({
|
|
47
|
+
schemas,
|
|
48
|
+
chatQuery,
|
|
49
|
+
chatEnabled = false,
|
|
50
|
+
}: {
|
|
51
|
+
schemas: Schema[];
|
|
52
|
+
chatQuery?: string;
|
|
53
|
+
chatEnabled: boolean;
|
|
54
|
+
}) {
|
|
55
|
+
const [buttonText, setButtonText] = useState('Copy page');
|
|
56
|
+
|
|
57
|
+
// get the url of the current page
|
|
58
|
+
const url = window.location.href;
|
|
59
|
+
const markdownUrl = url + '.mdx';
|
|
60
|
+
|
|
61
|
+
// Fetch the markdown from the url + .mdx
|
|
62
|
+
const copyMarkdownToClipboard = async () => {
|
|
63
|
+
console.log('Copying markdown to clipboard');
|
|
64
|
+
try {
|
|
65
|
+
setButtonText('Copied');
|
|
66
|
+
const response = await fetch(markdownUrl);
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
69
|
+
}
|
|
70
|
+
const markdown = await response.text();
|
|
71
|
+
await navigator.clipboard.writeText(markdown);
|
|
72
|
+
setTimeout(() => setButtonText('Copy page'), 3000); // Revert after 3 seconds
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Failed to copy markdown:', error);
|
|
75
|
+
setButtonText('Copy failed'); // Provide feedback on failure
|
|
76
|
+
setTimeout(() => setButtonText('Copy page'), 3000);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Fetch the schema from the schemaURL and copy it to the clipboard
|
|
81
|
+
const copySchemaToClipboard = async (schema: Schema) => {
|
|
82
|
+
if (!schema.url) return; // Should not happen if button is hidden, but good practice
|
|
83
|
+
|
|
84
|
+
console.log('Copying schema to clipboard from:', schema.url);
|
|
85
|
+
try {
|
|
86
|
+
setButtonText('Copied Schema');
|
|
87
|
+
const response = await fetch(schema.url); // Use the provided schemaURL directly
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
90
|
+
}
|
|
91
|
+
const schemaContent = await response.text(); // Or response.json() if it's always JSON
|
|
92
|
+
await navigator.clipboard.writeText(schemaContent);
|
|
93
|
+
setTimeout(() => setButtonText('Copy page'), 3000); // Revert after 3 seconds
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('Failed to copy schema:', error);
|
|
96
|
+
setButtonText('Copy failed'); // Provide feedback on failure
|
|
97
|
+
setTimeout(() => setButtonText('Copy page'), 3000);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<DropdownMenu.Root>
|
|
103
|
+
{/* Container for the split button */}
|
|
104
|
+
<div className="inline-flex rounded-md shadow-sm border border-gray-300">
|
|
105
|
+
{/* Left Button: Copy Action */}
|
|
106
|
+
<button
|
|
107
|
+
type="button"
|
|
108
|
+
onClick={copyMarkdownToClipboard}
|
|
109
|
+
className="inline-flex items-center justify-center gap-1 px-3 py-1.5 text-sm font-medium text-gray-700 bg-white rounded-l-md hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500"
|
|
110
|
+
>
|
|
111
|
+
<Copy className="w-4 h-4" />
|
|
112
|
+
{buttonText}
|
|
113
|
+
</button>
|
|
114
|
+
{/* Right Button: Dropdown Trigger */}
|
|
115
|
+
<DropdownMenu.Trigger asChild>
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
className="inline-flex items-center justify-center px-1.5 py-1.5 text-sm font-medium text-gray-500 bg-white rounded-r-md border-l border-gray-300 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500"
|
|
119
|
+
aria-label="More options"
|
|
120
|
+
>
|
|
121
|
+
<ChevronDownIcon className="w-4 h-4" />
|
|
122
|
+
</button>
|
|
123
|
+
</DropdownMenu.Trigger>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
{/* Adjust styling for the content dropdown */}
|
|
127
|
+
<DropdownMenu.Content
|
|
128
|
+
className="w-72 bg-white rounded-lg shadow-lg border border-gray-200 mt-1 py-1"
|
|
129
|
+
sideOffset={5}
|
|
130
|
+
align="end"
|
|
131
|
+
>
|
|
132
|
+
<DropdownMenu.Item
|
|
133
|
+
className="cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
|
|
134
|
+
onSelect={() => copyMarkdownToClipboard()}
|
|
135
|
+
>
|
|
136
|
+
<MenuItemContent icon={Copy} title="Copy page" description="Copy page as Markdown for LLMs" />
|
|
137
|
+
</DropdownMenu.Item>
|
|
138
|
+
|
|
139
|
+
{schemas.map((schema) => {
|
|
140
|
+
const title =
|
|
141
|
+
schema.format === 'asyncapi'
|
|
142
|
+
? 'Copy AsyncAPI specification'
|
|
143
|
+
: schema.format === 'openapi'
|
|
144
|
+
? 'Copy OpenAPI specification'
|
|
145
|
+
: 'Copy schema';
|
|
146
|
+
const type =
|
|
147
|
+
schema.format === 'asyncapi' || schema.format === 'openapi'
|
|
148
|
+
? 'specification'
|
|
149
|
+
: `${schema.format.toUpperCase()} schema`;
|
|
150
|
+
|
|
151
|
+
const Icon =
|
|
152
|
+
schema.format === 'asyncapi' ? (
|
|
153
|
+
<img src={buildUrl('/icons/asyncapi.svg', true)} className="w-4 h-4" />
|
|
154
|
+
) : schema.format === 'openapi' ? (
|
|
155
|
+
<img src={buildUrl('/icons/openapi.svg', true)} className="w-4 h-4" />
|
|
156
|
+
) : (
|
|
157
|
+
FileText
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<DropdownMenu.Item
|
|
162
|
+
className="cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
|
|
163
|
+
onSelect={() => copySchemaToClipboard(schema)}
|
|
164
|
+
>
|
|
165
|
+
<MenuItemContent icon={Icon} title={title} description={`Copy ${type} to clipboard`} />
|
|
166
|
+
</DropdownMenu.Item>
|
|
167
|
+
);
|
|
168
|
+
})}
|
|
169
|
+
<DropdownMenu.Item
|
|
170
|
+
className="cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
|
|
171
|
+
onSelect={() => window.open(markdownUrl, '_blank')}
|
|
172
|
+
>
|
|
173
|
+
<MenuItemContent icon={FileText} title="View as Markdown" description="View this page as plain text" external={true} />
|
|
174
|
+
</DropdownMenu.Item>
|
|
175
|
+
{chatEnabled && (
|
|
176
|
+
<DropdownMenu.Item
|
|
177
|
+
className="cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
|
|
178
|
+
onSelect={() => window.open(buildUrl(`/chat?query=${chatQuery}`))}
|
|
179
|
+
>
|
|
180
|
+
{/* Using MessageCircleQuestion as a placeholder for Claude logo */}
|
|
181
|
+
<MenuItemContent
|
|
182
|
+
icon={MessageCircleQuestion}
|
|
183
|
+
title="Open in EventCatalog Chat"
|
|
184
|
+
description="Ask questions about this page"
|
|
185
|
+
external={true}
|
|
186
|
+
/>
|
|
187
|
+
</DropdownMenu.Item>
|
|
188
|
+
)}
|
|
189
|
+
</DropdownMenu.Content>
|
|
190
|
+
</DropdownMenu.Root>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export default CopyPageMenu;
|
|
@@ -11,6 +11,7 @@ import RepositoryList from '@components/Lists/RepositoryList.astro';
|
|
|
11
11
|
import { getOwner } from '@utils/collections/owners';
|
|
12
12
|
import CustomSideBarSectionList from '@components/Lists/CustomSideBarSectionList.astro';
|
|
13
13
|
import config from '@config';
|
|
14
|
+
import { getSchemaFormatFromURL } from '@utils/collections/schemas';
|
|
14
15
|
|
|
15
16
|
interface Props {
|
|
16
17
|
message: CollectionEntry<CollectionMessageTypes>;
|
|
@@ -182,7 +183,7 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
|
|
|
182
183
|
class="flex items-center justify-center space-x-2 text-center rounded-md w-full bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-100/60 hover:text-primary"
|
|
183
184
|
>
|
|
184
185
|
<FileDownIcon strokeWidth={2} size={16} />
|
|
185
|
-
<span>Download schema</span>
|
|
186
|
+
<span>Download {getSchemaFormatFromURL(schemaURL)?.toUpperCase()} schema</span>
|
|
186
187
|
</a>
|
|
187
188
|
)
|
|
188
189
|
}
|
package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.client.tsx
CHANGED
|
@@ -3,7 +3,6 @@ import { BookOpen, Send } from 'lucide-react';
|
|
|
3
3
|
import { CreateWebWorkerMLCEngine, type InitProgressReport } from '@mlc-ai/web-llm';
|
|
4
4
|
import { useChat, type Message } from '../hooks/ChatProvider';
|
|
5
5
|
import React from 'react';
|
|
6
|
-
|
|
7
6
|
// Update Message type to include resources
|
|
8
7
|
interface Resource {
|
|
9
8
|
id: string;
|
|
@@ -122,9 +121,11 @@ const ChatWindow = ({
|
|
|
122
121
|
const [isThinking, setIsThinking] = useState(false);
|
|
123
122
|
const completionRef = useRef<any>(null);
|
|
124
123
|
const outputRef = useRef<HTMLDivElement>(null);
|
|
124
|
+
const [sendDefaultQuestionToLLM, setSendDefaultQuestionToLLM] = useState(false);
|
|
125
125
|
|
|
126
126
|
const { currentSession, storeMessagesToSession, updateSession, isStreaming, setIsStreaming } = useChat();
|
|
127
127
|
|
|
128
|
+
// Load messages when session changes
|
|
128
129
|
// Load messages when session changes
|
|
129
130
|
useEffect(() => {
|
|
130
131
|
if (currentSession) {
|
|
@@ -159,6 +160,7 @@ const ChatWindow = ({
|
|
|
159
160
|
}, [engine]);
|
|
160
161
|
|
|
161
162
|
const handleSubmit = useCallback(async () => {
|
|
163
|
+
console.log('handleSubmit', inputValue);
|
|
162
164
|
if (!inputValue.trim() || !engine) return;
|
|
163
165
|
|
|
164
166
|
// Add to messages
|
|
@@ -360,6 +362,13 @@ const ChatWindow = ({
|
|
|
360
362
|
}
|
|
361
363
|
};
|
|
362
364
|
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
if (!loading && sendDefaultQuestionToLLM) {
|
|
367
|
+
handleSubmit();
|
|
368
|
+
setSendDefaultQuestionToLLM(false);
|
|
369
|
+
}
|
|
370
|
+
}, [sendDefaultQuestionToLLM, loading]);
|
|
371
|
+
|
|
363
372
|
useEffect(() => {
|
|
364
373
|
const initEngine = async () => {
|
|
365
374
|
try {
|
|
@@ -447,6 +456,16 @@ const ChatWindow = ({
|
|
|
447
456
|
setInputValue(e.target.value);
|
|
448
457
|
}, []);
|
|
449
458
|
|
|
459
|
+
// If we have an initial query, set the input value
|
|
460
|
+
useEffect(() => {
|
|
461
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
462
|
+
const query = urlParams.get('query');
|
|
463
|
+
if (query) {
|
|
464
|
+
setInputValue(query);
|
|
465
|
+
setSendDefaultQuestionToLLM(true);
|
|
466
|
+
}
|
|
467
|
+
}, []);
|
|
468
|
+
|
|
450
469
|
return (
|
|
451
470
|
<div className="flex-1 flex flex-col overflow-hidden h-[calc(100vh-60px)] w-full">
|
|
452
471
|
{/* Chat Messages */}
|
package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.server.tsx
CHANGED
|
@@ -49,7 +49,7 @@ const ChatWindow = ({
|
|
|
49
49
|
const [isInputModalOpen, setIsInputModalOpen] = useState(false);
|
|
50
50
|
// --- End new state ---
|
|
51
51
|
|
|
52
|
-
const { currentSession, storeMessagesToSession, updateSession, isStreaming, setIsStreaming } = useChat();
|
|
52
|
+
const { currentSession, storeMessagesToSession, updateSession, isStreaming, setIsStreaming, createSession } = useChat();
|
|
53
53
|
|
|
54
54
|
// If the messages change add them to the session
|
|
55
55
|
useEffect(() => {
|
|
@@ -415,6 +415,18 @@ const ChatWindow = ({
|
|
|
415
415
|
};
|
|
416
416
|
}, []); // Empty dependency array ensures this runs only once on mount
|
|
417
417
|
|
|
418
|
+
// Handle the query from the url
|
|
419
|
+
useEffect(() => {
|
|
420
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
421
|
+
const query = urlParams.get('query');
|
|
422
|
+
if (query) {
|
|
423
|
+
setTimeout(() => {
|
|
424
|
+
createSession();
|
|
425
|
+
setInputValue(query);
|
|
426
|
+
}, 250);
|
|
427
|
+
}
|
|
428
|
+
}, []);
|
|
429
|
+
|
|
418
430
|
return (
|
|
419
431
|
<div className="flex-1 flex flex-col overflow-hidden h-[calc(100vh-60px)] w-full bg-white">
|
|
420
432
|
{/* Main content area - renders messages or predefined questions */}
|
|
@@ -15,6 +15,8 @@ import DomainSideBar from '@components/SideBars/DomainSideBar.astro';
|
|
|
15
15
|
import ChannelSideBar from '@components/SideBars/ChannelSideBar.astro';
|
|
16
16
|
import FlowSideBar from '@components/SideBars/FlowSideBar.astro';
|
|
17
17
|
import EntitySideBar from '@components/SideBars/EntitySideBar.astro';
|
|
18
|
+
import CopyAsMarkdown from '@components/CopyAsMarkdown';
|
|
19
|
+
|
|
18
20
|
import {
|
|
19
21
|
QueueListIcon,
|
|
20
22
|
RectangleGroupIcon,
|
|
@@ -36,6 +38,9 @@ import { getIcon } from '@utils/badges';
|
|
|
36
38
|
import { getDeprecatedDetails } from '@utils/collections/util';
|
|
37
39
|
import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
|
|
38
40
|
import { buildUrl } from '@utils/url-builder';
|
|
41
|
+
import { getSchemasFromResource } from '@utils/collections/schemas';
|
|
42
|
+
import { isEventCatalogChatEnabled, isMarkdownDownloadEnabled } from '@utils/feature';
|
|
43
|
+
|
|
39
44
|
import config from '@config';
|
|
40
45
|
|
|
41
46
|
export async function getStaticPaths() {
|
|
@@ -176,6 +181,14 @@ const {
|
|
|
176
181
|
|
|
177
182
|
let friendlyCollectionName = props.collection.slice(0, props.collection.length - 1);
|
|
178
183
|
friendlyCollectionName = friendlyCollectionName === 'querie' ? 'query' : friendlyCollectionName;
|
|
184
|
+
|
|
185
|
+
const schemasForResource = getSchemasFromResource(props);
|
|
186
|
+
|
|
187
|
+
const generatePromptForResource = (props: any) => {
|
|
188
|
+
return `
|
|
189
|
+
Please tell me more about the ${props.collection.slice(0, props.collection.length - 1)} - ${props.data.name} v${props.data.version} in this catalog.
|
|
190
|
+
`;
|
|
191
|
+
};
|
|
179
192
|
---
|
|
180
193
|
|
|
181
194
|
<VerticalSideBarLayout title={pageTitle} description={props.data.summary}>
|
|
@@ -184,13 +197,27 @@ friendlyCollectionName = friendlyCollectionName === 'querie' ? 'query' : friendl
|
|
|
184
197
|
<div class="w-full lg:mr-2 pr-8 overflow-y-auto py-8">
|
|
185
198
|
<div class="border-b border-gray-200 md:pb-2">
|
|
186
199
|
<div>
|
|
187
|
-
<
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
200
|
+
<div class="flex justify-between items-center">
|
|
201
|
+
<h2
|
|
202
|
+
id="doc-page-header"
|
|
203
|
+
class={`text-2xl md:text-4xl font-bold text-black ${props.data.deprecated && hasDeprecated ? 'text-red-500' : ''}`}
|
|
204
|
+
>
|
|
205
|
+
{props.data.name}
|
|
206
|
+
<span class="">(v{props.data.version})</span>
|
|
207
|
+
</h2>
|
|
208
|
+
{
|
|
209
|
+
isMarkdownDownloadEnabled() && (
|
|
210
|
+
<div class="hidden lg:block">
|
|
211
|
+
<CopyAsMarkdown
|
|
212
|
+
client:only="react"
|
|
213
|
+
schemas={schemasForResource}
|
|
214
|
+
chatQuery={generatePromptForResource(props)}
|
|
215
|
+
chatEnabled={isEventCatalogChatEnabled()}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
</div>
|
|
194
221
|
{
|
|
195
222
|
isMarkedAsDeprecated && hasDeprecated && (
|
|
196
223
|
<Admonition
|
|
@@ -11,7 +11,6 @@ import { isCustomLandingPageEnabled } from '@utils/feature';
|
|
|
11
11
|
import DefaultAstroLandingPage from './_index.astro';
|
|
12
12
|
|
|
13
13
|
let nodeGraphs: any[] = [];
|
|
14
|
-
|
|
15
14
|
let CustomContent = null;
|
|
16
15
|
|
|
17
16
|
import path from 'path';
|
|
@@ -22,7 +21,10 @@ const props = Astro.props;
|
|
|
22
21
|
const pathToUserDefinedLandingPage = path.join(process.env.PROJECT_DIR || '', 'pages/homepage.astro');
|
|
23
22
|
|
|
24
23
|
if (existsSync(pathToUserDefinedLandingPage) && isCustomLandingPageEnabled()) {
|
|
25
|
-
|
|
24
|
+
const customPages = import.meta.glob('/**/homepage.astro', { eager: true });
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
CustomContent = Object.values(customPages)[0]?.default || null;
|
|
27
|
+
|
|
26
28
|
const rawContent = readFileSync(pathToUserDefinedLandingPage, 'utf-8');
|
|
27
29
|
nodeGraphs = getMDXComponentsByName(rawContent, 'NodeGraph') || [];
|
|
28
30
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { CollectionEntry } from 'astro:content';
|
|
2
|
+
import type { PageTypes } from '@types';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { buildUrl } from '@utils/url-builder';
|
|
5
|
+
|
|
6
|
+
export type Schema = {
|
|
7
|
+
url: string;
|
|
8
|
+
format: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const getSchemaURL = (resource: CollectionEntry<PageTypes>) => {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
const publicPath = resource?.catalog?.publicPath;
|
|
14
|
+
const schemaFilePath = resource?.data?.schemaPath;
|
|
15
|
+
|
|
16
|
+
if (!publicPath || !schemaFilePath) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// new URL
|
|
21
|
+
return path.join(publicPath, schemaFilePath);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getSchemaFormatFromURL = (url: string) => {
|
|
25
|
+
const pathParts = url.split('.');
|
|
26
|
+
const format = pathParts[pathParts.length - 1];
|
|
27
|
+
return format;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const getSchemasFromResource = (resource: CollectionEntry<PageTypes>): Schema[] => {
|
|
31
|
+
const schemaPublicPath = getSchemaURL(resource);
|
|
32
|
+
|
|
33
|
+
if (!schemaPublicPath) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (resource.collection === 'services') {
|
|
38
|
+
const asyncapiPath = resource?.data?.specifications?.asyncapiPath;
|
|
39
|
+
const openapiPath = resource?.data?.specifications?.openapiPath;
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
const publicPath = resource?.catalog?.publicPath;
|
|
42
|
+
const schemas = [];
|
|
43
|
+
|
|
44
|
+
if (asyncapiPath) {
|
|
45
|
+
const asyncapiUrl = path.join(publicPath, asyncapiPath);
|
|
46
|
+
schemas.push({ url: buildUrl(asyncapiUrl), format: 'asyncapi' });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (openapiPath) {
|
|
50
|
+
const openapiUrl = path.join(publicPath, openapiPath);
|
|
51
|
+
schemas.push({ url: buildUrl(openapiUrl), format: 'openapi' });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return schemas;
|
|
55
|
+
} else {
|
|
56
|
+
const pathParts = schemaPublicPath.split('.');
|
|
57
|
+
const format = pathParts[pathParts.length - 1];
|
|
58
|
+
return [{ url: buildUrl(schemaPublicPath), format }];
|
|
59
|
+
}
|
|
60
|
+
};
|
|
@@ -11,12 +11,19 @@
|
|
|
11
11
|
* 3. Follow the official activation instructions
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import config from '@config';
|
|
15
|
+
|
|
14
16
|
// These functions check for valid, legally obtained access to premium features
|
|
15
17
|
export const isEventCatalogStarterEnabled = () => process.env.EVENTCATALOG_STARTER === 'true';
|
|
16
18
|
export const isEventCatalogScaleEnabled = () => process.env.EVENTCATALOG_SCALE === 'true';
|
|
17
19
|
|
|
18
20
|
export const isCustomDocsEnabled = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
|
|
19
|
-
export const isEventCatalogChatEnabled = () =>
|
|
21
|
+
export const isEventCatalogChatEnabled = () => {
|
|
22
|
+
const isFeatureEnabledFromPlan = isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
|
|
23
|
+
return isFeatureEnabledFromPlan && config?.chat?.enabled;
|
|
24
|
+
};
|
|
20
25
|
|
|
21
26
|
export const isEventCatalogUpgradeEnabled = () => !isEventCatalogStarterEnabled() && !isEventCatalogScaleEnabled();
|
|
22
27
|
export const isCustomLandingPageEnabled = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
|
|
28
|
+
|
|
29
|
+
export const isMarkdownDownloadEnabled = () => config?.llmsTxt?.enabled ?? false;
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/event-catalog/eventcatalog.git"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
|
-
"version": "2.37.
|
|
9
|
+
"version": "2.37.2",
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"@parcel/watcher": "^2.4.1",
|
|
45
45
|
"@radix-ui/react-context-menu": "^2.2.6",
|
|
46
46
|
"@radix-ui/react-dialog": "^1.1.6",
|
|
47
|
+
"@radix-ui/react-dropdown-menu": "^2.1.12",
|
|
47
48
|
"@radix-ui/react-tooltip": "^1.1.8",
|
|
48
49
|
"@scalar/api-reference-react": "^0.4.37",
|
|
49
50
|
"@tailwindcss/typography": "^0.5.13",
|