@eventcatalog/core 2.37.1 → 2.37.3

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.
@@ -37,7 +37,7 @@ var import_axios = __toESM(require("axios"), 1);
37
37
  var import_os = __toESM(require("os"), 1);
38
38
 
39
39
  // package.json
40
- var version = "2.37.1";
40
+ var version = "2.37.3";
41
41
 
42
42
  // src/constants.ts
43
43
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-2TAZVC65.js";
4
- import "../chunk-V5DKJ3VX.js";
3
+ } from "../chunk-RXERG5SL.js";
4
+ import "../chunk-KC74WARE.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -106,7 +106,7 @@ var import_axios = __toESM(require("axios"), 1);
106
106
  var import_os = __toESM(require("os"), 1);
107
107
 
108
108
  // package.json
109
- var version = "2.37.1";
109
+ var version = "2.37.3";
110
110
 
111
111
  // src/constants.ts
112
112
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-ENZA5AV5.js";
4
- import "../chunk-2TAZVC65.js";
5
- import "../chunk-V5DKJ3VX.js";
3
+ } from "../chunk-JCZFOKW3.js";
4
+ import "../chunk-RXERG5SL.js";
5
+ import "../chunk-KC74WARE.js";
6
6
  import "../chunk-E7TXTI7G.js";
7
7
  export {
8
8
  log_build_default as default
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-2TAZVC65.js";
3
+ } from "./chunk-RXERG5SL.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "2.37.1";
2
+ var version = "2.37.3";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-V5DKJ3VX.js";
3
+ } from "./chunk-KC74WARE.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "2.37.1";
28
+ var version = "2.37.3";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-V5DKJ3VX.js";
3
+ } from "./chunk-KC74WARE.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -157,7 +157,7 @@ var import_axios = __toESM(require("axios"), 1);
157
157
  var import_os = __toESM(require("os"), 1);
158
158
 
159
159
  // package.json
160
- var version = "2.37.1";
160
+ var version = "2.37.3";
161
161
 
162
162
  // src/constants.ts
163
163
  var VERSION = version;
@@ -6,15 +6,15 @@ import {
6
6
  } from "./chunk-DCLTVJDP.js";
7
7
  import {
8
8
  log_build_default
9
- } from "./chunk-ENZA5AV5.js";
10
- import "./chunk-2TAZVC65.js";
9
+ } from "./chunk-JCZFOKW3.js";
10
+ import "./chunk-RXERG5SL.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-V5DKJ3VX.js";
17
+ } from "./chunk-KC74WARE.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
  }
@@ -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 */}
@@ -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 */}
@@ -8,6 +8,8 @@ import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
8
8
  import SchemaViewer from '@components/MDX/SchemaViewer/SchemaViewerRoot.astro';
9
9
  import Admonition from '@components/MDX/Admonition';
10
10
 
11
+ import { resourceToCollectionMap, collectionToResourceMap } from '@utils/collections/util';
12
+
11
13
  // SideBars
12
14
  import ServiceSideBar from '@components/SideBars/ServiceSideBar.astro';
13
15
  import MessageSideBar from '@components/SideBars/MessageSideBar.astro';
@@ -15,6 +17,8 @@ import DomainSideBar from '@components/SideBars/DomainSideBar.astro';
15
17
  import ChannelSideBar from '@components/SideBars/ChannelSideBar.astro';
16
18
  import FlowSideBar from '@components/SideBars/FlowSideBar.astro';
17
19
  import EntitySideBar from '@components/SideBars/EntitySideBar.astro';
20
+ import CopyAsMarkdown from '@components/CopyAsMarkdown';
21
+
18
22
  import {
19
23
  QueueListIcon,
20
24
  RectangleGroupIcon,
@@ -36,6 +40,11 @@ import { getIcon } from '@utils/badges';
36
40
  import { getDeprecatedDetails } from '@utils/collections/util';
37
41
  import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
38
42
  import { buildUrl } from '@utils/url-builder';
43
+ import { getSchemasFromResource } from '@utils/collections/schemas';
44
+ import { isEventCatalogChatEnabled, isMarkdownDownloadEnabled } from '@utils/feature';
45
+
46
+ import { getMDXComponentsByName } from '@utils/markdown';
47
+
39
48
  import config from '@config';
40
49
 
41
50
  export async function getStaticPaths() {
@@ -60,6 +69,7 @@ export async function getStaticPaths() {
60
69
  const props = Astro.props;
61
70
 
62
71
  const { Content } = await render(props);
72
+
63
73
  // const { Content } = await props.render();
64
74
 
65
75
  // Capitalize the first letter of a string
@@ -176,6 +186,23 @@ const {
176
186
 
177
187
  let friendlyCollectionName = props.collection.slice(0, props.collection.length - 1);
178
188
  friendlyCollectionName = friendlyCollectionName === 'querie' ? 'query' : friendlyCollectionName;
189
+
190
+ const schemasForResource = getSchemasFromResource(props);
191
+
192
+ const generatePromptForResource = (props: any) => {
193
+ return `
194
+ Please tell me more about the ${props.collection.slice(0, props.collection.length - 1)} - ${props.data.name} v${props.data.version} in this catalog.
195
+ `;
196
+ };
197
+
198
+ // Handle node graphs in the markdown
199
+ let nodeGraphs = getMDXComponentsByName(props.body || '', 'NodeGraph') || [];
200
+
201
+ nodeGraphs.push({
202
+ id: props.data.id,
203
+ version: props.data.version,
204
+ type: collectionToResourceMap[props.collection as keyof typeof collectionToResourceMap],
205
+ });
179
206
  ---
180
207
 
181
208
  <VerticalSideBarLayout title={pageTitle} description={props.data.summary}>
@@ -184,13 +211,27 @@ friendlyCollectionName = friendlyCollectionName === 'querie' ? 'query' : friendl
184
211
  <div class="w-full lg:mr-2 pr-8 overflow-y-auto py-8">
185
212
  <div class="border-b border-gray-200 md:pb-2">
186
213
  <div>
187
- <h2
188
- id="doc-page-header"
189
- class={`text-2xl md:text-4xl font-bold text-black ${props.data.deprecated && hasDeprecated ? 'text-red-500' : ''}`}
190
- >
191
- {props.data.name}
192
- <span class="">(v{props.data.version})</span>
193
- </h2>
214
+ <div class="flex justify-between items-center">
215
+ <h2
216
+ id="doc-page-header"
217
+ class={`text-2xl md:text-4xl font-bold text-black ${props.data.deprecated && hasDeprecated ? 'text-red-500' : ''}`}
218
+ >
219
+ {props.data.name}
220
+ <span class="">(v{props.data.version})</span>
221
+ </h2>
222
+ {
223
+ isMarkdownDownloadEnabled() && (
224
+ <div class="hidden lg:block">
225
+ <CopyAsMarkdown
226
+ client:only="react"
227
+ schemas={schemasForResource}
228
+ chatQuery={generatePromptForResource(props)}
229
+ chatEnabled={isEventCatalogChatEnabled()}
230
+ />
231
+ </div>
232
+ )
233
+ }
234
+ </div>
194
235
  {
195
236
  isMarkedAsDeprecated && hasDeprecated && (
196
237
  <Admonition
@@ -292,17 +333,27 @@ friendlyCollectionName = friendlyCollectionName === 'querie' ? 'query' : friendl
292
333
  <!-- @ts-ignore -->
293
334
  <!-- <SchemaViewer id={props.data.id} catalog={props.catalog} filePath={props.filePath} /> -->
294
335
  <SchemaViewer id={props.data.id} filePath={props.filePath} />
295
- <NodeGraph
296
- id={props.data.id}
297
- collection={props.collection}
298
- version={props.data.version}
299
- mode="simple"
300
- linksToVisualiser={true}
301
- href={{
302
- label: 'Open in Visualiser',
303
- url: buildUrl(`/visualiser/${props.collection}/${props.data.id}/${props.data.version}`),
304
- }}
305
- />
336
+
337
+ {
338
+ nodeGraphs.length > 0 &&
339
+ nodeGraphs.map((nodeGraph: any) => {
340
+ const collection = resourceToCollectionMap[nodeGraph.type as keyof typeof resourceToCollectionMap];
341
+ return (
342
+ <NodeGraph
343
+ id={nodeGraph.id}
344
+ version={nodeGraph.version}
345
+ collection={collection}
346
+ title={nodeGraph.title}
347
+ mode="simple"
348
+ linksToVisualiser={true}
349
+ href={{
350
+ label: 'Open in Visualiser',
351
+ url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
352
+ }}
353
+ />
354
+ );
355
+ })
356
+ }
306
357
  </div>
307
358
  <Footer />
308
359
  </div>
@@ -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
+ };
@@ -110,6 +110,18 @@ export const resourceToCollectionMap = {
110
110
  team: 'teams',
111
111
  } as const;
112
112
 
113
+ export const collectionToResourceMap = {
114
+ services: 'service',
115
+ events: 'event',
116
+ commands: 'command',
117
+ queries: 'query',
118
+ domains: 'domain',
119
+ flows: 'flow',
120
+ channels: 'channel',
121
+ users: 'user',
122
+ teams: 'team',
123
+ } as const;
124
+
113
125
  export const getDeprecatedDetails = (item: CollectionEntry<CollectionTypes>) => {
114
126
  let options = {
115
127
  isMarkedAsDeprecated: false,
@@ -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 = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
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.1",
9
+ "version": "2.37.3",
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",