@eventcatalog/core 2.51.0 → 2.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,7 +34,7 @@
34
34
  <h4>Features: Documentation for Event Driven Architectures, Integration with any broker, Generator from your OpenAPI and AsyncAPI documents, Docs and Code, Markdown driven, Document Domains/Services/Messages/Schemas and more, Content versioning, Assign Owners, Schemas, OpenAPI, MDX Components and more...</h4>
35
35
 
36
36
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
37
- [![All Contributors](https://img.shields.io/badge/all_contributors-54-orange.svg?style=flat-square)](#contributors-)
37
+ [![All Contributors](https://img.shields.io/badge/all_contributors-55-orange.svg?style=flat-square)](#contributors-)
38
38
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
39
39
 
40
40
  [Read the Docs](https://www.eventcatalog.dev/docs/development/getting-started/introduction) | [View Demo](https://demo.eventcatalog.dev)
@@ -265,6 +265,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
265
265
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/VitaliiBalash"><img src="https://avatars.githubusercontent.com/u/4520809?v=4?s=100" width="100px;" alt="Vitalii Balash"/><br /><sub><b>Vitalii Balash</b></sub></a><br /><a href="https://github.com/event-catalog/eventcatalog/commits?author=VitaliiBalash" title="Code">💻</a></td>
266
266
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/ababilone"><img src="https://avatars.githubusercontent.com/u/925013?v=4?s=100" width="100px;" alt="Arnaud Babilone"/><br /><sub><b>Arnaud Babilone</b></sub></a><br /><a href="https://github.com/event-catalog/eventcatalog/commits?author=ababilone" title="Code">💻</a></td>
267
267
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/alexanderhorner"><img src="https://avatars.githubusercontent.com/u/18349361?v=4?s=100" width="100px;" alt="Alexander Horner"/><br /><sub><b>Alexander Horner</b></sub></a><br /><a href="https://github.com/event-catalog/eventcatalog/commits?author=alexanderhorner" title="Code">💻</a></td>
268
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/simonwfarrow"><img src="https://avatars.githubusercontent.com/u/3245908?v=4?s=100" width="100px;" alt="simonwfarrow"/><br /><sub><b>simonwfarrow</b></sub></a><br /><a href="https://github.com/event-catalog/eventcatalog/commits?author=simonwfarrow" title="Code">💻</a></td>
268
269
  </tr>
269
270
  </tbody>
270
271
  </table>
@@ -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.0";
40
+ var version = "2.52.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-2J3EYRYN.js";
4
- import "../chunk-CXGJYRWV.js";
3
+ } from "../chunk-6DB32LQO.js";
4
+ import "../chunk-GR53VD3Z.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.0";
109
+ var version = "2.52.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-PRFUGFES.js";
4
- import "../chunk-2J3EYRYN.js";
5
- import "../chunk-CXGJYRWV.js";
3
+ } from "../chunk-IXFKZMN2.js";
4
+ import "../chunk-6DB32LQO.js";
5
+ import "../chunk-GR53VD3Z.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-CXGJYRWV.js";
3
+ } from "./chunk-GR53VD3Z.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "2.51.0";
2
+ var version = "2.52.0";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-2J3EYRYN.js";
3
+ } from "./chunk-6DB32LQO.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -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.0";
28
+ var version = "2.52.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-CXGJYRWV.js";
3
+ } from "./chunk-GR53VD3Z.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.0";
160
+ var version = "2.52.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-PRFUGFES.js";
10
- import "./chunk-2J3EYRYN.js";
9
+ } from "./chunk-IXFKZMN2.js";
10
+ import "./chunk-6DB32LQO.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-CXGJYRWV.js";
18
+ } from "./chunk-GR53VD3Z.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
  },
@@ -5,7 +5,7 @@ import Admonition from '@components/MDX/Admonition';
5
5
  import NodeGraph from '../NodeGraph/NodeGraph';
6
6
  import { getVersionFromCollection } from '@utils/collections/versions';
7
7
 
8
- const { id, version = 'latest', maxHeight, includeKey = true } = Astro.props;
8
+ const { id, version = 'latest', maxHeight, includeKey = true, entities } = Astro.props;
9
9
 
10
10
  // Find the flow for the given id and version
11
11
  const domains = await getDomains();
@@ -15,6 +15,7 @@ const domain = domainCollection[0];
15
15
  const { nodes, edges } = await getNodesAndEdges({
16
16
  id: id,
17
17
  version: domain?.data?.version,
18
+ ...(entities ? { entities } : {}), // Pass entities if provided
18
19
  });
19
20
  ---
20
21
 
@@ -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 }),
@@ -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
@@ -12,17 +12,25 @@ const elk = new ELK();
12
12
  interface Props {
13
13
  id: string;
14
14
  version: string;
15
+ entities?: string[]; // Optional: array of entity IDs/names to include
15
16
  }
16
17
 
17
- export const getNodesAndEdges = async ({ id, version }: Props) => {
18
+ export const getNodesAndEdges = async ({ id, version, entities }: Props) => {
18
19
  let nodes = [] as any,
19
20
  edges = [] as any;
20
21
 
21
22
  const allDomains = await getDomains();
22
- const entities = await getEntities();
23
+ const allEntities = await getEntities();
23
24
 
24
25
  const domain = getVersionFromCollection(allDomains, id, version)[0] as Domain;
25
- const domainEntities = (domain?.data?.entities ?? []) as any;
26
+ let domainEntities = (domain?.data?.entities ?? []) as any;
27
+
28
+ // If entities filter is provided, filter domainEntities to only those specified
29
+ if (entities && Array.isArray(entities) && entities.length > 0) {
30
+ domainEntities = domainEntities.filter(
31
+ (entity: Entity) => entities.includes(entity.data.id) || entities.includes(entity.data.name)
32
+ );
33
+ }
26
34
 
27
35
  const entitiesWithReferences = domainEntities.filter((entity: Entity) =>
28
36
  entity.data.properties?.some((property: any) => property.references)
@@ -44,7 +52,7 @@ export const getNodesAndEdges = async ({ id, version }: Props) => {
44
52
  .flat()
45
53
  .filter((ref: any) => ref !== undefined);
46
54
 
47
- const externalToDomain = [...new Set(listOfReferencedEntities)] // Remove duplicates
55
+ const externalToDomain = Array.from(new Set<string>(listOfReferencedEntities as string[])) // Remove duplicates
48
56
  .filter((entityId: any) => !domainEntities.some((domainEntity: any) => domainEntity.id === entityId));
49
57
 
50
58
  // Helper function to find which domain an entity belongs to
@@ -54,7 +62,7 @@ export const getNodesAndEdges = async ({ id, version }: Props) => {
54
62
 
55
63
  const addedExternalEntities = [];
56
64
  for (const entityId of externalToDomain) {
57
- const externalEntity = getItemsFromCollectionByIdAndSemverOrLatest(entities, entityId as string, 'latest')[0] as Entity;
65
+ const externalEntity = getItemsFromCollectionByIdAndSemverOrLatest(allEntities, entityId as string, 'latest')[0] as Entity;
58
66
 
59
67
  if (externalEntity) {
60
68
  const nodeId = generateIdForNode(externalEntity);
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.0",
9
+ "version": "2.52.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",