@eventcatalog/core 2.51.1 → 2.53.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.
@@ -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.51.1";
40
+ var version = "2.53.0";
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-IAZKU3ZK.js";
4
- import "../chunk-GWDFHYDT.js";
3
+ } from "../chunk-AYGHOQI3.js";
4
+ import "../chunk-UPR7DQB2.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.51.1";
109
+ var version = "2.53.0";
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-JH4IFYVJ.js";
4
- import "../chunk-IAZKU3ZK.js";
5
- import "../chunk-GWDFHYDT.js";
3
+ } from "../chunk-K5EGYLT5.js";
4
+ import "../chunk-AYGHOQI3.js";
5
+ import "../chunk-UPR7DQB2.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
  VERSION
3
- } from "./chunk-GWDFHYDT.js";
3
+ } from "./chunk-UPR7DQB2.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-IAZKU3ZK.js";
3
+ } from "./chunk-AYGHOQI3.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "2.51.1";
2
+ var version = "2.53.0";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "2.51.1";
28
+ var version = "2.53.0";
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-GWDFHYDT.js";
3
+ } from "./chunk-UPR7DQB2.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.51.1";
160
+ var version = "2.53.0";
161
161
 
162
162
  // src/constants.ts
163
163
  var VERSION = version;
@@ -6,8 +6,8 @@ import {
6
6
  } from "./chunk-XE6PFSH5.js";
7
7
  import {
8
8
  log_build_default
9
- } from "./chunk-JH4IFYVJ.js";
10
- import "./chunk-IAZKU3ZK.js";
9
+ } from "./chunk-K5EGYLT5.js";
10
+ import "./chunk-AYGHOQI3.js";
11
11
  import {
12
12
  catalogToAstro,
13
13
  checkAndConvertMdToMdx
@@ -15,7 +15,7 @@ import {
15
15
  import "./chunk-LDBRNJIL.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-GWDFHYDT.js";
18
+ } from "./chunk-UPR7DQB2.js";
19
19
  import {
20
20
  isAuthEnabled,
21
21
  isBackstagePluginEnabled,
@@ -92,6 +92,11 @@ export default defineConfig({
92
92
  */
93
93
  '__EC_TRAILING_SLASH__': config.trailingSlash || false,
94
94
  },
95
+ server: {
96
+ fs: {
97
+ allow: ['..', './node_modules/@fontsource']
98
+ }
99
+ },
95
100
  worker: {
96
101
  format: 'es',
97
102
  },
@@ -0,0 +1,177 @@
1
+ ---
2
+ import jsonpath from 'jsonpath';
3
+ import SchemaViewer from './SchemaViewer/SchemaViewer.astro';
4
+ import { Code } from 'astro-expressive-code/components';
5
+ import { isPrivateRemoteSchemaEnabled } from '@utils/feature';
6
+
7
+ const {
8
+ url,
9
+ headers = {},
10
+ jsonPath = null,
11
+ renderAs = 'auto',
12
+ title = 'Remote Schema',
13
+ maxHeight = '400',
14
+ ...props
15
+ } = Astro.props;
16
+
17
+ function resolveTemplates(input: any): any {
18
+ if (typeof input === 'string') {
19
+ return input.replace(/\$\{(\w+)\}/g, (_, varName) => import.meta.env[varName] || '');
20
+ }
21
+
22
+ if (typeof input === 'object' && input !== null) {
23
+ return Object.fromEntries(Object.entries(input).map(([k, v]) => [k, resolveTemplates(v)]));
24
+ }
25
+
26
+ return input;
27
+ }
28
+
29
+ function isValidJSON(str: string): boolean {
30
+ try {
31
+ JSON.parse(str);
32
+ return true;
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ function isJSONSchema(data: any): boolean {
39
+ if (!data || typeof data !== 'object') return false;
40
+
41
+ // Check for common JSON Schema indicators
42
+ const hasSchemaIndicators =
43
+ data.$schema ||
44
+ data.type ||
45
+ data.properties ||
46
+ data.items ||
47
+ data.definitions ||
48
+ data.$defs ||
49
+ data.allOf ||
50
+ data.oneOf ||
51
+ data.anyOf ||
52
+ (data.components && data.components.schemas); // OpenAPI style
53
+
54
+ return Boolean(hasSchemaIndicators);
55
+ }
56
+
57
+ function extractWithJSONPath(data: any, path: string): any {
58
+ try {
59
+ const result = jsonpath.query(data, path);
60
+ // If the result is an array with a single element, return the element itself
61
+ // unless the original query was meant to return an array
62
+ if (Array.isArray(result) && result.length === 1 && !path.includes('[*]') && !path.includes('.*')) {
63
+ return result[0];
64
+ }
65
+ return result.length > 0 ? result : data;
66
+ } catch (error) {
67
+ console.error('JSONPath error:', error);
68
+ return data;
69
+ }
70
+ }
71
+
72
+ const resolvedUrl = resolveTemplates(url);
73
+ const resolvedHeaders = isPrivateRemoteSchemaEnabled() ? resolveTemplates(headers) : {};
74
+
75
+ let content = '';
76
+ let processedData: any = null;
77
+ let contentType = 'text';
78
+ let isSchema = false;
79
+ let error = null;
80
+ let showPaidFeatureMessage = false;
81
+
82
+ // Check if headers were provided but private remote schema is not enabled
83
+ if (Object.keys(headers).length > 0 && !isPrivateRemoteSchemaEnabled()) {
84
+ error = '401 Unauthorized - Headers provided but private remote schema feature is not enabled';
85
+ showPaidFeatureMessage = true;
86
+ }
87
+
88
+ try {
89
+ const response = await fetch(resolvedUrl, {
90
+ headers: resolvedHeaders,
91
+ });
92
+
93
+ if (!response.ok) {
94
+ throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
95
+ }
96
+
97
+ content = await response.text();
98
+
99
+ // Detect content type
100
+ if (isValidJSON(content)) {
101
+ contentType = 'json';
102
+ processedData = JSON.parse(content);
103
+
104
+ // Check if it's a JSON Schema
105
+ isSchema = isJSONSchema(processedData);
106
+
107
+ // Apply JSONPath if provided
108
+ if (jsonPath) {
109
+ content = extractWithJSONPath(processedData, jsonPath);
110
+ } else {
111
+ content = JSON.stringify(processedData, null, 2);
112
+ }
113
+ }
114
+ } catch (e) {
115
+ if (!showPaidFeatureMessage) {
116
+ error = e instanceof Error ? e.message : String(e);
117
+ }
118
+ }
119
+
120
+ // Determine rendering method
121
+ let finalRenderAs = renderAs;
122
+ if (renderAs === 'auto') {
123
+ if (contentType === 'json' && isSchema) {
124
+ finalRenderAs = 'schema';
125
+ } else {
126
+ finalRenderAs = 'raw';
127
+ }
128
+ }
129
+ ---
130
+
131
+ {
132
+ error ? (
133
+ <div class="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded not-prose">
134
+ <strong>
135
+ Error loading remote file: <span class=" text-red-900">{url}</span>
136
+ </strong>
137
+ <p class="text-xs py-2">{` ${error} `}</p>
138
+ {showPaidFeatureMessage && (
139
+ <div class="my-1 p-3 bg-white border border-gray-200 rounded text-gray-700">
140
+ <strong>Private API Access</strong>
141
+ <p class="mt-1 text-xs">
142
+ Fetching files from private APIs with headers is a paid feature.
143
+ <a href="https://eventcatalog.cloud" class="underline hover:no-underline" target="_blank" rel="noopener noreferrer">
144
+ Sign up for a EventCatalog Scale license key
145
+ </a>{' '}
146
+ to access this functionality.
147
+ </p>
148
+ </div>
149
+ )}
150
+ </div>
151
+ ) : (
152
+ <div class="remote-file-content">
153
+ {finalRenderAs === 'schema' ? (
154
+ <SchemaViewer
155
+ schema={processedData}
156
+ schemaPath={resolvedUrl}
157
+ title={title}
158
+ maxHeight={maxHeight}
159
+ file="remote"
160
+ id={`remote-schema-${Math.random().toString(36).substring(2, 9)}`}
161
+ expand={false}
162
+ search={true}
163
+ />
164
+ ) : (
165
+ <div class="not-prose max-w-4xl overflow-x-auto" style={`max-height: ${maxHeight}px;`}>
166
+ <Code code={content} title={title || ''} lang="json" />
167
+ </div>
168
+ )}
169
+
170
+ {jsonPath && (
171
+ <div class="mt-2 text-xs text-gray-500">
172
+ Applied JSONPath: <code class="bg-gray-100 px-1 rounded">{jsonPath}</code>
173
+ </div>
174
+ )}
175
+ </div>
176
+ )
177
+ }
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { isSSR } from '@utils/feature';
3
+ import Admonition from './Admonition';
4
+ import RemoteFile from './RemoteFile.astro';
5
+ const { url, headers, jsonPath, renderAs, ...props } = Astro.props;
6
+ ---
7
+
8
+ {
9
+ isSSR() ? (
10
+ <RemoteFile url={url} headers={headers} jsonPath={jsonPath} renderAs={renderAs} {...props} />
11
+ ) : (
12
+ <Admonition type="warning">
13
+ <div>
14
+ <span class="block font-bold">{`<RemoteSchema/>`} is only available on the server</span>
15
+ <span class="block">
16
+ You are trying to load a remote file, but this component is not supported in the client. You must switch to SSR mode to
17
+ use this component.
18
+ </span>
19
+ </div>
20
+ </Admonition>
21
+ )
22
+ }
@@ -28,6 +28,7 @@ import FigJam from '@components/MDX/FigJam/FigJam.astro';
28
28
  import NodeGraphPortal from '@components/MDX/NodeGraph/NodeGraphPortal';
29
29
  import SchemaViewerPortal from '@components/MDX/SchemaViewer/SchemaViewerPortal';
30
30
  import { jsx } from 'astro/jsx-runtime';
31
+ import RemoteSchema from '@components/MDX/RemoteSchema.astro';
31
32
 
32
33
  const components = (props: any) => {
33
34
  return {
@@ -37,6 +38,7 @@ const components = (props: any) => {
37
38
  AsyncAPI,
38
39
  ChannelInformation: (mdxProp: any) => ChannelInformation({ ...props.data, ...mdxProp }),
39
40
  File: (mdxProp: any) => File({ ...props, ...mdxProp }),
41
+ RemoteSchema,
40
42
  Flow,
41
43
  Link: (mdxProp: any) => jsx(Link, { ...props, ...mdxProp }),
42
44
  MessageTable: (mdxProp: any) => jsx(MessageTable, { ...props, ...mdxProp }),
@@ -75,12 +75,20 @@ const consumersList = consumers.map((c) => ({
75
75
  tag: `v${c.data.version}`,
76
76
  href: buildUrl(`/docs/${c.collection}/${c.data.id}/${c.data.version}`),
77
77
  }));
78
+
79
+ const shouldRenderSideBarSection = (section: string) => {
80
+ if (!channel.data.detailsPanel) {
81
+ return true;
82
+ }
83
+ // @ts-ignore
84
+ return channel.data.detailsPanel[section]?.visible ?? true;
85
+ };
78
86
  ---
79
87
 
80
88
  <aside class="sticky top-28 left-0 space-y-8 h-full overflow-y-auto py-4">
81
89
  <div class="">
82
90
  {
83
- producersList.length > 0 && (
91
+ producersList.length > 0 && shouldRenderSideBarSection('producers') && (
84
92
  <PillListFlat
85
93
  title={`Producers (${producersList.length})`}
86
94
  pills={producersList}
@@ -92,7 +100,7 @@ const consumersList = consumers.map((c) => ({
92
100
  }
93
101
 
94
102
  {
95
- consumersList.length > 0 && (
103
+ consumersList.length > 0 && shouldRenderSideBarSection('consumers') && (
96
104
  <PillListFlat
97
105
  title={`Consumers (${consumersList.length})`}
98
106
  pills={consumersList}
@@ -104,7 +112,7 @@ const consumersList = consumers.map((c) => ({
104
112
  }
105
113
 
106
114
  {
107
- messageList.length > 0 && (
115
+ messageList.length > 0 && shouldRenderSideBarSection('messages') && (
108
116
  <PillListFlat
109
117
  title={`Messages using channel (${messageList.length})`}
110
118
  pills={messageList}
@@ -116,13 +124,13 @@ const consumersList = consumers.map((c) => ({
116
124
  }
117
125
 
118
126
  {
119
- protocolList.length > 0 && (
127
+ protocolList.length > 0 && shouldRenderSideBarSection('protocols') && (
120
128
  <ProtocolList color="pink" title={`Protocols (${protocolList.length})`} pills={protocolList} client:load />
121
129
  )
122
130
  }
123
131
 
124
132
  {
125
- channel.data.versions && (
133
+ channel.data.versions && shouldRenderSideBarSection('versions') && (
126
134
  <VersionList
127
135
  title={`Versions (${channel.data.versions?.length})`}
128
136
  versions={channel.data.versions}
@@ -131,27 +139,31 @@ const consumersList = consumers.map((c) => ({
131
139
  )
132
140
  }
133
141
 
134
- <OwnersList
135
- title={`Owners (${filteredOwners.length})`}
136
- owners={ownersList}
137
- emptyMessage={`This channel does not have any documented owners.`}
138
- client:load
139
- />
142
+ {
143
+ ownersList.length > 0 && shouldRenderSideBarSection('owners') && (
144
+ <OwnersList
145
+ title={`Owners (${filteredOwners.length})`}
146
+ owners={ownersList}
147
+ emptyMessage={`This channel does not have any documented owners.`}
148
+ client:load
149
+ />
150
+ )
151
+ }
140
152
 
141
153
  {
142
- channel.data.repository && (
154
+ channel.data.repository && shouldRenderSideBarSection('repository') && (
143
155
  <RepositoryList repository={channel.data.repository?.url} language={channel.data.repository?.language} />
144
156
  )
145
157
  }
146
158
 
147
159
  {
148
- paramsList.length > 0 && (
160
+ paramsList.length > 0 && shouldRenderSideBarSection('parameters') && (
149
161
  <PillListFlat color="pink" title={`Parameters (${paramsList.length})`} pills={paramsList} client:load />
150
162
  )
151
163
  }
152
164
 
153
165
  {
154
- isChangelogEnabled() && (
166
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
155
167
  <div class="space-y-2">
156
168
  <a
157
169
  href={buildUrl(`/docs/${channel.collection}/${channel.data.id}/${channel.data.latestVersion}/changelog`)}
@@ -105,12 +105,20 @@ const ownersList = filteredOwners.map((o) => ({
105
105
  avatarUrl: o.collection === 'users' ? o.data.avatarUrl : '',
106
106
  href: buildUrl(`/docs/${o.collection}/${o.data.id}`),
107
107
  }));
108
+
109
+ const shouldRenderSideBarSection = (section: string) => {
110
+ if (!domain.data.detailsPanel) {
111
+ return true;
112
+ }
113
+ // @ts-ignore
114
+ return domain.data.detailsPanel[section]?.visible ?? true;
115
+ };
108
116
  ---
109
117
 
110
118
  <aside class="sticky top-28 left-0 space-y-8 h-full overflow-y-auto py-4">
111
119
  <div>
112
120
  {
113
- parentDomains.length > 0 && (
121
+ parentDomains.length > 0 && shouldRenderSideBarSection('parentDomains') && (
114
122
  <PillListFlat
115
123
  title={`Parent domains (${parentDomains.length})`}
116
124
  pills={parentDomainList}
@@ -123,7 +131,7 @@ const ownersList = filteredOwners.map((o) => ({
123
131
  }
124
132
 
125
133
  {
126
- subDomains.length > 0 && (
134
+ subDomains.length > 0 && shouldRenderSideBarSection('subdomains') && (
127
135
  <PillListFlat
128
136
  title={`Subdomains (${subDomains.length})`}
129
137
  pills={subDomainList}
@@ -139,29 +147,41 @@ const ownersList = filteredOwners.map((o) => ({
139
147
  .filter((section) => section.items.length > 0 && section.sidebar)
140
148
  .map((section) => <CustomSideBarSectionList section={section} />)
141
149
  }
142
- <PillListFlat
143
- title={`Services (${services.length})`}
144
- pills={serviceList}
145
- emptyMessage={`This domain does not contain any services.`}
146
- color="pink"
147
- client:load
148
- />
149
- <PillListFlat
150
- title={`Sends messages (${sendsList.length})`}
151
- pills={sendsList}
152
- emptyMessage={`This domain does not send any messages.`}
153
- color="orange"
154
- client:load
155
- />
156
- <PillListFlat
157
- title={`Receives messages (${receivesList.length})`}
158
- pills={receivesList}
159
- emptyMessage={`This domain does not receive any messages.`}
160
- color="orange"
161
- client:load
162
- />
163
150
  {
164
- ubiquitousLanguageList && hasUbiquitousLanguage && (
151
+ shouldRenderSideBarSection('services') && (
152
+ <PillListFlat
153
+ title={`Services (${services.length})`}
154
+ pills={serviceList}
155
+ emptyMessage={`This domain does not contain any services.`}
156
+ color="pink"
157
+ client:load
158
+ />
159
+ )
160
+ }
161
+ {
162
+ shouldRenderSideBarSection('messages') && (
163
+ <PillListFlat
164
+ title={`Sends messages (${sendsList.length})`}
165
+ pills={sendsList}
166
+ emptyMessage={`This domain does not send any messages.`}
167
+ color="orange"
168
+ client:load
169
+ />
170
+ )
171
+ }
172
+ {
173
+ shouldRenderSideBarSection('messages') && (
174
+ <PillListFlat
175
+ title={`Receives messages (${receivesList.length})`}
176
+ pills={receivesList}
177
+ emptyMessage={`This domain does not receive any messages.`}
178
+ color="orange"
179
+ client:load
180
+ />
181
+ )
182
+ }
183
+ {
184
+ ubiquitousLanguageList && hasUbiquitousLanguage && shouldRenderSideBarSection('ubiquitousLanguage') && (
165
185
  <PillListFlat
166
186
  title={`Ubiquitous Language Dictionary (${ubiquitousLanguageDictionary?.length})`}
167
187
  pills={ubiquitousLanguageList}
@@ -173,7 +193,7 @@ const ownersList = filteredOwners.map((o) => ({
173
193
  )
174
194
  }
175
195
  {
176
- entities.length > 0 && (
196
+ entities.length > 0 && shouldRenderSideBarSection('entities') && (
177
197
  <PillListFlat
178
198
  title={`Entities (${entities.length})`}
179
199
  pills={entityList}
@@ -183,18 +203,26 @@ const ownersList = filteredOwners.map((o) => ({
183
203
  />
184
204
  )
185
205
  }
186
- {domain.data.versions && <VersionList versions={domain.data.versions} collectionItem={domain} />}
187
206
  {
188
- domain.data.repository && (
207
+ domain.data.versions && shouldRenderSideBarSection('versions') && (
208
+ <VersionList versions={domain.data.versions} collectionItem={domain} />
209
+ )
210
+ }
211
+ {
212
+ domain.data.repository && shouldRenderSideBarSection('repository') && (
189
213
  <RepositoryList repository={domain.data.repository?.url} language={domain.data.repository?.language} />
190
214
  )
191
215
  }
192
- <OwnersList
193
- title={`Owners (${ownersList.length})`}
194
- owners={ownersList}
195
- emptyMessage={`This domain does not have any documented owners.`}
196
- client:load
197
- />
216
+ {
217
+ shouldRenderSideBarSection('owners') && (
218
+ <OwnersList
219
+ title={`Owners (${ownersList.length})`}
220
+ owners={ownersList}
221
+ emptyMessage={`This domain does not have any documented owners.`}
222
+ client:load
223
+ />
224
+ )
225
+ }
198
226
 
199
227
  <div class="space-y-2">
200
228
  <a
@@ -205,7 +233,7 @@ const ownersList = filteredOwners.map((o) => ({
205
233
  <span class="block">View in visualiser</span>
206
234
  </a>
207
235
  {
208
- isChangelogEnabled() && (
236
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
209
237
  <a
210
238
  href={buildUrl(`/docs/${domain.collection}/${domain.data.id}/${domain.data.latestVersion}/changelog`)}
211
239
  class="flex items-center space-x-2 justify-center 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"
@@ -48,12 +48,20 @@ const domainsList = domains.map((p) => ({
48
48
  tag: `v${p.data.version}`,
49
49
  href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
50
50
  }));
51
+
52
+ const shouldRenderSideBarSection = (section: string) => {
53
+ if (!entity.data.detailsPanel) {
54
+ return true;
55
+ }
56
+ // @ts-ignore
57
+ return entity.data.detailsPanel[section]?.visible ?? true;
58
+ };
51
59
  ---
52
60
 
53
61
  <aside class="sticky top-28 left-0 space-y-8 h-full overflow-y-auto py-4">
54
62
  <div class="">
55
63
  {
56
- (
64
+ shouldRenderSideBarSection('domains') && (
57
65
  <PillListFlat
58
66
  title={`Domains (${domainsList.length})`}
59
67
  pills={domainsList}
@@ -64,7 +72,7 @@ const domainsList = domains.map((p) => ({
64
72
  )
65
73
  }
66
74
  {
67
- servicesList.length > 0 && (
75
+ servicesList.length > 0 && shouldRenderSideBarSection('services') && (
68
76
  <PillListFlat
69
77
  title={`Services (${servicesList.length})`}
70
78
  pills={servicesList}
@@ -74,16 +82,24 @@ const domainsList = domains.map((p) => ({
74
82
  />
75
83
  )
76
84
  }
77
- {entity.data.versions && <VersionList versions={entity.data.versions} collectionItem={entity} />}
78
- <OwnersList
79
- title={`Owners (${filteredOwners.length})`}
80
- owners={ownersList}
81
- emptyMessage={`This entity does not have any documented owners.`}
82
- client:load
83
- />
85
+ {
86
+ entity.data.versions && shouldRenderSideBarSection('versions') && (
87
+ <VersionList versions={entity.data.versions} collectionItem={entity} />
88
+ )
89
+ }
90
+ {
91
+ filteredOwners.length > 0 && shouldRenderSideBarSection('owners') && (
92
+ <OwnersList
93
+ title={`Owners (${filteredOwners.length})`}
94
+ owners={ownersList}
95
+ emptyMessage={`This entity does not have any documented owners.`}
96
+ client:load
97
+ />
98
+ )
99
+ }
84
100
 
85
101
  {
86
- isChangelogEnabled() && (
102
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
87
103
  <div class="space-y-2">
88
104
  <a
89
105
  href={buildUrl(`/docs/${entity.collection}/${entity.data.id}/${entity.data.latestVersion}/changelog`)}
@@ -29,6 +29,14 @@ const ownersList = filteredOwners.map((o) => ({
29
29
  }));
30
30
 
31
31
  const isRSSEnabled = config.rss?.enabled;
32
+
33
+ const shouldRenderSideBarSection = (section: string) => {
34
+ if (!flow.data.detailsPanel) {
35
+ return true;
36
+ }
37
+ // @ts-ignore
38
+ return flow.data.detailsPanel[section]?.visible ?? true;
39
+ };
32
40
  ---
33
41
 
34
42
  <aside class="sticky top-28 left-0 h-full overflow-y-auto pr-6 py-4">
@@ -38,14 +46,22 @@ const isRSSEnabled = config.rss?.enabled;
38
46
  .filter((section) => section.items.length > 0 && section.sidebar)
39
47
  .map((section) => <CustomSideBarSectionList section={section} />)
40
48
  }
41
- {flow.data.versions && <VersionList versions={flow.data.versions} collectionItem={flow} />}
49
+ {
50
+ flow.data.versions && shouldRenderSideBarSection('versions') && (
51
+ <VersionList versions={flow.data.versions} collectionItem={flow} />
52
+ )
53
+ }
42
54
 
43
- <OwnersList
44
- title={`Owners (${ownersList.length})`}
45
- owners={ownersList}
46
- emptyMessage={`This flow does not have any documented owners.`}
47
- client:load
48
- />
55
+ {
56
+ shouldRenderSideBarSection('owners') && (
57
+ <OwnersList
58
+ title={`Owners (${ownersList.length})`}
59
+ owners={ownersList}
60
+ emptyMessage={`This flow does not have any documented owners.`}
61
+ client:load
62
+ />
63
+ )
64
+ }
49
65
 
50
66
  {
51
67
  isRSSEnabled && (
@@ -72,7 +88,7 @@ const isRSSEnabled = config.rss?.enabled;
72
88
  <span class="block">View in visualiser</span>
73
89
  </a>
74
90
  {
75
- isChangelogEnabled() && (
91
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
76
92
  <a
77
93
  href={buildUrl(`/docs/${flow.collection}/${flow.data.id}/${flow.data.latestVersion}/changelog`)}
78
94
  class="flex items-center space-x-2 justify-center 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"
@@ -98,6 +98,14 @@ const publicPath = message?.catalog?.publicPath;
98
98
 
99
99
  const schemaFilePath = message?.data?.schemaPath;
100
100
  const schemaURL = path.join(publicPath, schemaFilePath || '');
101
+
102
+ const shouldRenderSideBarSection = (section: string) => {
103
+ if (!message.data.detailsPanel) {
104
+ return true;
105
+ }
106
+ // @ts-ignore
107
+ return message.data.detailsPanel[section]?.visible ?? true;
108
+ };
101
109
  ---
102
110
 
103
111
  <aside class="sticky top-28 left-0 space-y-8 h-full overflow-y-auto py-4">
@@ -108,7 +116,7 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
108
116
  .map((section) => <CustomSideBarSectionList section={section} />)
109
117
  }
110
118
  {
111
- producerList.length > 0 && (
119
+ producerList.length > 0 && shouldRenderSideBarSection('producers') && (
112
120
  <PillListFlat
113
121
  color="pink"
114
122
  title={`Producers (${producerList.length})`}
@@ -119,7 +127,7 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
119
127
  )
120
128
  }
121
129
  {
122
- consumerList.length > 0 && (
130
+ consumerList.length > 0 && shouldRenderSideBarSection('consumers') && (
123
131
  <PillListFlat
124
132
  color="pink"
125
133
  title={`Consumers (${consumerList.length})`}
@@ -130,13 +138,13 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
130
138
  )
131
139
  }
132
140
  {
133
- channelList.length > 0 && (
141
+ channelList.length > 0 && shouldRenderSideBarSection('channels') && (
134
142
  <PillListFlat color="pink" title={`Channels (${channelList.length})`} pills={channelList} client:load />
135
143
  )
136
144
  }
137
145
 
138
146
  {
139
- message.data.versions && (
147
+ message.data.versions && shouldRenderSideBarSection('versions') && (
140
148
  <VersionList
141
149
  title={`Versions (${message.data.versions?.length})`}
142
150
  versions={message.data.versions}
@@ -145,15 +153,19 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
145
153
  )
146
154
  }
147
155
 
148
- <OwnersList
149
- title={`Owners (${ownersList.length})`}
150
- owners={ownersList}
151
- emptyMessage={`This ${type} does not have any documented owners.`}
152
- client:load
153
- />
156
+ {
157
+ ownersList.length > 0 && shouldRenderSideBarSection('owners') && (
158
+ <OwnersList
159
+ title={`Owners (${ownersList.length})`}
160
+ owners={ownersList}
161
+ emptyMessage={`This ${type} does not have any documented owners.`}
162
+ client:load
163
+ />
164
+ )
165
+ }
154
166
 
155
167
  {
156
- message.data.repository && (
168
+ message.data.repository && shouldRenderSideBarSection('repository') && (
157
169
  <RepositoryList repository={message.data.repository?.url} language={message.data.repository?.language} />
158
170
  )
159
171
  }
@@ -196,7 +208,7 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
196
208
  </a>
197
209
 
198
210
  {
199
- isChangelogEnabled() && (
211
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
200
212
  <a
201
213
  href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.latestVersion}/changelog`)}
202
214
  class="flex items-center space-x-2 justify-center 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"
@@ -87,6 +87,14 @@ const isRSSEnabled = config.rss?.enabled;
87
87
  const publicPath = service?.catalog?.publicPath;
88
88
  const schemaFilePath = service?.data?.schemaPath;
89
89
  const schemaURL = join(publicPath, schemaFilePath || '');
90
+
91
+ const shouldRenderSideBarSection = (section: string) => {
92
+ if (!service.data.detailsPanel) {
93
+ return true;
94
+ }
95
+ // @ts-ignore
96
+ return service.data.detailsPanel[section]?.visible ?? true;
97
+ };
90
98
  ---
91
99
 
92
100
  <aside class="sticky top-28 left-0 h-full overflow-y-auto pr-6 py-4">
@@ -97,7 +105,7 @@ const schemaURL = join(publicPath, schemaFilePath || '');
97
105
  .map((section) => <CustomSideBarSectionList section={section} />)
98
106
  }
99
107
  {
100
- domainList.length > 0 && (
108
+ domainList.length > 0 && shouldRenderSideBarSection('domains') && (
101
109
  <PillListFlat
102
110
  title={`Domains (${domainList.length})`}
103
111
  pills={domainList}
@@ -107,26 +115,40 @@ const schemaURL = join(publicPath, schemaFilePath || '');
107
115
  />
108
116
  )
109
117
  }
110
- <PillListFlat
111
- title={`Receives Messages (${receivesList.length})`}
112
- pills={receivesList}
113
- emptyMessage={`This service does not receive any messages.`}
114
- color="orange"
115
- client:load
116
- />
117
- <PillListFlat
118
- title={`Sends Messages (${sendsList.length})`}
119
- pills={sendsList}
120
- emptyMessage={`This service does not send any messages.`}
121
- color="orange"
122
- client:load
123
- />
124
- {service.data.versions && <VersionList versions={service.data.versions} collectionItem={service} />}
125
-
126
- {service.data.specifications && <SpecificationsList collectionItem={service} />}
118
+ {
119
+ shouldRenderSideBarSection('messages') && (
120
+ <>
121
+ <PillListFlat
122
+ title={`Receives Messages (${receivesList.length})`}
123
+ pills={receivesList}
124
+ emptyMessage={`This service does not receive any messages.`}
125
+ color="orange"
126
+ client:load
127
+ />
128
+ <PillListFlat
129
+ title={`Sends Messages (${sendsList.length})`}
130
+ pills={sendsList}
131
+ emptyMessage={`This service does not send any messages.`}
132
+ color="orange"
133
+ client:load
134
+ />
135
+ </>
136
+ )
137
+ }
138
+ {
139
+ service.data.versions && shouldRenderSideBarSection('versions') && (
140
+ <VersionList versions={service.data.versions} collectionItem={service} />
141
+ )
142
+ }
143
+
144
+ {
145
+ service.data.specifications && shouldRenderSideBarSection('specifications') && (
146
+ <SpecificationsList collectionItem={service} />
147
+ )
148
+ }
127
149
 
128
150
  {
129
- entities.length > 0 && (
151
+ entities.length > 0 && shouldRenderSideBarSection('entities') && (
130
152
  <PillListFlat
131
153
  title={`Entities (${entities.length})`}
132
154
  pills={entityList}
@@ -137,15 +159,19 @@ const schemaURL = join(publicPath, schemaFilePath || '');
137
159
  )
138
160
  }
139
161
 
140
- <OwnersList
141
- title={`Owners (${ownersList.length})`}
142
- owners={ownersList}
143
- emptyMessage={`This service does not have any documented owners.`}
144
- client:load
145
- />
162
+ {
163
+ shouldRenderSideBarSection('owners') && (
164
+ <OwnersList
165
+ title={`Owners (${ownersList.length})`}
166
+ owners={ownersList}
167
+ emptyMessage={`This service does not have any documented owners.`}
168
+ client:load
169
+ />
170
+ )
171
+ }
146
172
 
147
173
  {
148
- service.data.repository && (
174
+ service.data.repository && shouldRenderSideBarSection('repository') && (
149
175
  <RepositoryList repository={service.data.repository?.url} language={service.data.repository?.language} />
150
176
  )
151
177
  }
@@ -187,7 +213,7 @@ const schemaURL = join(publicPath, schemaFilePath || '');
187
213
  <span class="block">View in visualiser</span>
188
214
  </a>
189
215
  {
190
- isChangelogEnabled() && (
216
+ isChangelogEnabled() && shouldRenderSideBarSection('changelog') && (
191
217
  <a
192
218
  href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.latestVersion}/changelog`)}
193
219
  class="flex items-center space-x-2 justify-center 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"
@@ -31,6 +31,10 @@ const pointer = z.object({
31
31
  version: z.string().optional().default('latest'),
32
32
  });
33
33
 
34
+ const detailPanelPropertySchema = z.object({
35
+ visible: z.boolean().optional(),
36
+ });
37
+
34
38
  const channelPointer = z
35
39
  .object({
36
40
  parameters: z.record(z.string()).optional(),
@@ -175,6 +179,13 @@ const flows = defineCollection({
175
179
  }),
176
180
  schema: z
177
181
  .object({
182
+ detailsPanel: z
183
+ .object({
184
+ owners: detailPanelPropertySchema.optional(),
185
+ versions: detailPanelPropertySchema.optional(),
186
+ changelog: detailPanelPropertySchema.optional(),
187
+ })
188
+ .optional(),
178
189
  steps: z.array(
179
190
  z
180
191
  .object({
@@ -185,6 +196,7 @@ const flows = defineCollection({
185
196
  message: pointer.optional(),
186
197
  service: pointer.optional(),
187
198
  flow: pointer.optional(),
199
+
188
200
  actor: z
189
201
  .object({
190
202
  name: z.string(),
@@ -233,6 +245,16 @@ const flows = defineCollection({
233
245
  .merge(baseSchema),
234
246
  });
235
247
 
248
+ const messageDetailsPanelPropertySchema = z.object({
249
+ producers: detailPanelPropertySchema.optional(),
250
+ consumers: detailPanelPropertySchema.optional(),
251
+ channels: detailPanelPropertySchema.optional(),
252
+ versions: detailPanelPropertySchema.optional(),
253
+ repository: detailPanelPropertySchema.optional(),
254
+ owners: detailPanelPropertySchema.optional(),
255
+ changelog: detailPanelPropertySchema.optional(),
256
+ });
257
+
236
258
  const events = defineCollection({
237
259
  loader: glob({
238
260
  pattern: ['**/events/*/index.(md|mdx)', '**/events/*/versioned/*/index.(md|mdx)'],
@@ -248,6 +270,7 @@ const events = defineCollection({
248
270
  channels: z.array(channelPointer).optional(),
249
271
  // Used by eventcatalog
250
272
  messageChannels: z.array(reference('channels')).optional(),
273
+ detailsPanel: messageDetailsPanelPropertySchema.optional(),
251
274
  })
252
275
  .merge(baseSchema),
253
276
  });
@@ -265,6 +288,7 @@ const commands = defineCollection({
265
288
  producers: z.array(reference('services')).optional(),
266
289
  consumers: z.array(reference('services')).optional(),
267
290
  channels: z.array(channelPointer).optional(),
291
+ detailsPanel: messageDetailsPanelPropertySchema.optional(),
268
292
  // Used by eventcatalog
269
293
  messageChannels: z.array(reference('channels')).optional(),
270
294
  })
@@ -284,6 +308,7 @@ const queries = defineCollection({
284
308
  producers: z.array(reference('services')).optional(),
285
309
  consumers: z.array(reference('services')).optional(),
286
310
  channels: z.array(channelPointer).optional(),
311
+ detailsPanel: messageDetailsPanelPropertySchema.optional(),
287
312
  // Used by eventcatalog
288
313
  messageChannels: z.array(reference('channels')).optional(),
289
314
  })
@@ -314,6 +339,18 @@ const services = defineCollection({
314
339
  sends: z.array(pointer).optional(),
315
340
  receives: z.array(pointer).optional(),
316
341
  entities: z.array(pointer).optional(),
342
+ detailsPanel: z
343
+ .object({
344
+ domains: detailPanelPropertySchema.optional(),
345
+ messages: detailPanelPropertySchema.optional(),
346
+ versions: detailPanelPropertySchema.optional(),
347
+ specifications: detailPanelPropertySchema.optional(),
348
+ entities: detailPanelPropertySchema.optional(),
349
+ repository: detailPanelPropertySchema.optional(),
350
+ owners: detailPanelPropertySchema.optional(),
351
+ changelog: detailPanelPropertySchema.optional(),
352
+ })
353
+ .optional(),
317
354
  })
318
355
  .merge(baseSchema),
319
356
  });
@@ -356,6 +393,20 @@ const domains = defineCollection({
356
393
  services: z.array(pointer).optional(),
357
394
  domains: z.array(pointer).optional(),
358
395
  entities: z.array(pointer).optional(),
396
+ detailsPanel: z
397
+ .object({
398
+ parentDomains: detailPanelPropertySchema.optional(),
399
+ subdomains: detailPanelPropertySchema.optional(),
400
+ services: detailPanelPropertySchema.optional(),
401
+ entities: detailPanelPropertySchema.optional(),
402
+ messages: detailPanelPropertySchema.optional(),
403
+ ubiquitousLanguage: detailPanelPropertySchema.optional(),
404
+ repository: detailPanelPropertySchema.optional(),
405
+ versions: detailPanelPropertySchema.optional(),
406
+ owners: detailPanelPropertySchema.optional(),
407
+ changelog: detailPanelPropertySchema.optional(),
408
+ })
409
+ .optional(),
359
410
  })
360
411
  .merge(baseSchema),
361
412
  });
@@ -383,6 +434,19 @@ const channels = defineCollection({
383
434
  )
384
435
  .optional(),
385
436
  messages: z.array(z.object({ collection: z.string(), name: z.string(), ...pointer.shape })).optional(),
437
+ detailsPanel: z
438
+ .object({
439
+ producers: detailPanelPropertySchema.optional(),
440
+ consumers: detailPanelPropertySchema.optional(),
441
+ messages: detailPanelPropertySchema.optional(),
442
+ protocols: detailPanelPropertySchema.optional(),
443
+ parameters: detailPanelPropertySchema.optional(),
444
+ versions: detailPanelPropertySchema.optional(),
445
+ repository: detailPanelPropertySchema.optional(),
446
+ owners: detailPanelPropertySchema.optional(),
447
+ changelog: detailPanelPropertySchema.optional(),
448
+ })
449
+ .optional(),
386
450
  })
387
451
  .merge(baseSchema),
388
452
  });
@@ -438,6 +502,16 @@ const entities = defineCollection({
438
502
  .optional(),
439
503
  services: z.array(reference('services')).optional(),
440
504
  domains: z.array(reference('domains')).optional(),
505
+ detailsPanel: z
506
+ .object({
507
+ domains: detailPanelPropertySchema.optional(),
508
+ services: detailPanelPropertySchema.optional(),
509
+ messages: detailPanelPropertySchema.optional(),
510
+ versions: detailPanelPropertySchema.optional(),
511
+ owners: detailPanelPropertySchema.optional(),
512
+ changelog: detailPanelPropertySchema.optional(),
513
+ })
514
+ .optional(),
441
515
  })
442
516
 
443
517
  .merge(baseSchema),
@@ -19,6 +19,8 @@ import { join } from 'path';
19
19
  export const isEventCatalogStarterEnabled = () => process.env.EVENTCATALOG_STARTER === 'true';
20
20
  export const isEventCatalogScaleEnabled = () => process.env.EVENTCATALOG_SCALE === 'true';
21
21
 
22
+ export const isPrivateRemoteSchemaEnabled = () => isEventCatalogScaleEnabled() || isEventCatalogStarterEnabled();
23
+
22
24
  export const showEventCatalogBranding = () => {
23
25
  const override = process.env.EVENTCATALOG_SHOW_BRANDING;
24
26
  // if any value we return true
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.51.1",
9
+ "version": "2.53.0",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
@@ -77,6 +77,7 @@
77
77
  "gray-matter": "^4.0.3",
78
78
  "html-to-image": "^1.11.11",
79
79
  "js-yaml": "^4.1.0",
80
+ "jsonpath": "^1.1.1",
80
81
  "jsonwebtoken": "^9.0.2",
81
82
  "langchain": "^0.3.19",
82
83
  "lodash.debounce": "^4.0.8",
@@ -110,6 +111,7 @@
110
111
  "@types/dagre": "^0.7.52",
111
112
  "@types/diff": "^5.2.2",
112
113
  "@types/js-yaml": "^4.0.9",
114
+ "@types/jsonpath": "^0.2.4",
113
115
  "@types/jsonwebtoken": "^9.0.10",
114
116
  "@types/lodash.debounce": "^4.0.9",
115
117
  "@types/lodash.merge": "4.6.9",