@eventcatalog/core 2.5.0 → 2.5.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @eventcatalog/core
2
2
 
3
+ ## 2.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2bbccf8: feat(core): added new MDX component for Flows
8
+
3
9
  ## 2.5.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -113,7 +113,7 @@ You can see the markdown files that generated the website in the GitHub repo und
113
113
 
114
114
  Interested in collaborating with us? Our offerings include dedicated support, priority assistance, feature development, custom integrations, and more.
115
115
 
116
- Find more details on our [enterprise plan](https://eventcatalog.dev/enterprise).
116
+ Find more details on our [services page](https://eventcatalog.dev/services).
117
117
 
118
118
  # Looking for v1?
119
119
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eventcatalog/core",
3
3
  "type": "module",
4
- "version": "2.5.0",
4
+ "version": "2.5.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -0,0 +1,63 @@
1
+ ---
2
+ import { getFlows } from '@utils/flows/flows';
3
+ import { getNodesAndEdges } from '@utils/flows/node-graph';
4
+ import Admonition from '@components/MDX/Admonition';
5
+ import NodeGraph from '../NodeGraph/NodeGraph';
6
+ import { getVersionFromCollection } from '@utils/versions/versions';
7
+
8
+ const { id, version = 'latest', maxHeight, includeKey = true } = Astro.props;
9
+
10
+ // Find the flow for the given id and version
11
+ const flows = await getFlows();
12
+ const flowCollection = getVersionFromCollection(flows, id, version) || [];
13
+ const flow = flowCollection[0];
14
+
15
+ // const flow = flows.find((flow) => flow.data.id === id && flow.data.version === version);
16
+
17
+ const { nodes, edges } = await getNodesAndEdges({
18
+ id: id,
19
+ version: flow.data.version,
20
+ });
21
+ ---
22
+
23
+ {
24
+ !flow && (
25
+ <Admonition type="warning">
26
+ <>
27
+ <span class="block font-bold">{`<Flow/>`} failed to load</span>
28
+ <span class="block">
29
+ Tried to load flow id: {id} with version {version}. Make sure you have this flow defined in your project.
30
+ </span>
31
+ </>
32
+ </Admonition>
33
+ )
34
+ }
35
+
36
+ <div
37
+ class="h-[30em] my-6 mb-12 w-full relative border border-gray-200 rounded-md"
38
+ id={`${id}-portal`}
39
+ style={{
40
+ maxHeight: maxHeight ? `${maxHeight}em` : `30em`,
41
+ }}
42
+ >
43
+ </div>
44
+
45
+ <div>
46
+ <NodeGraph
47
+ id={id}
48
+ nodes={nodes}
49
+ edges={edges}
50
+ hrefLabel={'View in visualizer'}
51
+ href={`/visualiser/flows/${id}/${version}`}
52
+ linkTo={'visualiser'}
53
+ includeKey={includeKey}
54
+ footerLabel=`Flow diagram - ${flow.data.name} - v(${flow.data.version})`
55
+ client:load
56
+ />
57
+ </div>
58
+
59
+ <style is:global>
60
+ .react-flow__attribution {
61
+ display: none;
62
+ }
63
+ </style>
@@ -31,6 +31,7 @@ interface Props {
31
31
  includeBackground?: boolean;
32
32
  includeControls?: boolean;
33
33
  linkTo: 'docs' | 'visualiser';
34
+ includeKey?: boolean;
34
35
  }
35
36
 
36
37
  const getDocUrlForCollection = (collectionItem: CollectionEntry<CollectionTypes>) => {
@@ -41,7 +42,14 @@ const getVisualiserUrlForCollection = (collectionItem: CollectionEntry<Collectio
41
42
  };
42
43
 
43
44
  // const NodeGraphBuilder = ({ title, subtitle, includeBackground = true, includeControls = true }: Props) => {
44
- const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground = true, linkTo = 'docs' }: Props) => {
45
+ const NodeGraphBuilder = ({
46
+ nodes: initialNodes,
47
+ edges,
48
+ title,
49
+ includeBackground = true,
50
+ linkTo = 'docs',
51
+ includeKey = true,
52
+ }: Props) => {
45
53
  const nodeTypes = useMemo(
46
54
  () => ({
47
55
  services: ServiceNode,
@@ -89,25 +97,27 @@ const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground
89
97
  <DownloadButton filename={title} addPadding={!!title} />
90
98
  {includeBackground && <Background color="#bbb" gap={16} />}
91
99
  {includeBackground && <Controls />}
92
- <Panel position="bottom-right">
93
- <div className=" bg-white font-light px-4 text-[14px] shadow-md py-1 rounded-md">
94
- <span className="font-bold">Key</span>
95
- <ul>
96
- <li className="flex space-x-2 items-center text-[12px]">
97
- <span className="w-2 h-2 bg-orange-500 block" />
98
- <span className="block">Event</span>
99
- </li>
100
- <li className="flex space-x-2 items-center text-[12px]">
101
- <span className="w-2 h-2 bg-pink-500 block" />
102
- <span className="block">Service</span>
103
- </li>
104
- <li className="flex space-x-2 items-center text-[12px]">
105
- <span className="w-2 h-2 bg-blue-500 block" />
106
- <span className="block">Command</span>
107
- </li>
108
- </ul>
109
- </div>
110
- </Panel>
100
+ {includeKey && (
101
+ <Panel position="bottom-right">
102
+ <div className=" bg-white font-light px-4 text-[14px] shadow-md py-1 rounded-md">
103
+ <span className="font-bold">Key</span>
104
+ <ul>
105
+ <li className="flex space-x-2 items-center text-[12px]">
106
+ <span className="w-2 h-2 bg-orange-500 block" />
107
+ <span className="block">Event</span>
108
+ </li>
109
+ <li className="flex space-x-2 items-center text-[12px]">
110
+ <span className="w-2 h-2 bg-pink-500 block" />
111
+ <span className="block">Service</span>
112
+ </li>
113
+ <li className="flex space-x-2 items-center text-[12px]">
114
+ <span className="w-2 h-2 bg-blue-500 block" />
115
+ <span className="block">Command</span>
116
+ </li>
117
+ </ul>
118
+ </div>
119
+ </Panel>
120
+ )}
111
121
  </ReactFlow>
112
122
  );
113
123
  };
@@ -120,9 +130,21 @@ interface NodeGraphProps {
120
130
  nodes: Node[];
121
131
  edges: Edge[];
122
132
  linkTo: 'docs' | 'visualiser';
133
+ includeKey?: boolean;
134
+ footerLabel?: string;
123
135
  }
124
136
 
125
- const NodeGraph = ({ id, nodes, edges, title, href, linkTo = 'docs', hrefLabel = 'Open in visualiser' }: NodeGraphProps) => {
137
+ const NodeGraph = ({
138
+ id,
139
+ nodes,
140
+ edges,
141
+ title,
142
+ href,
143
+ linkTo = 'docs',
144
+ hrefLabel = 'Open in visualizer',
145
+ includeKey = true,
146
+ footerLabel,
147
+ }: NodeGraphProps) => {
126
148
  const [elem, setElem] = useState(null);
127
149
 
128
150
  useEffect(() => {
@@ -136,15 +158,23 @@ const NodeGraph = ({ id, nodes, edges, title, href, linkTo = 'docs', hrefLabel =
136
158
  <div>
137
159
  {createPortal(
138
160
  <ReactFlowProvider>
139
- <NodeGraphBuilder edges={edges} nodes={nodes} title={title} linkTo={linkTo} />
161
+ <NodeGraphBuilder edges={edges} nodes={nodes} title={title} linkTo={linkTo} includeKey={includeKey} />
162
+
163
+ <div className="flex justify-between">
164
+ {footerLabel && (
165
+ <div className="py-2 w-full text-left ">
166
+ <span className=" text-sm no-underline py-2 text-gray-300">{footerLabel}</span>
167
+ </div>
168
+ )}
140
169
 
141
- {href && (
142
- <div className="py-2 w-full text-right">
143
- <a className=" text-sm no-underline py-2 text-gray-800 hover:text-purple-500" href={href}>
144
- {hrefLabel} &rarr;
145
- </a>
146
- </div>
147
- )}
170
+ {href && (
171
+ <div className="py-2 w-full text-right">
172
+ <a className=" text-sm no-underline py-2 text-gray-800 hover:text-purple-500" href={href}>
173
+ {hrefLabel} &rarr;
174
+ </a>
175
+ </div>
176
+ )}
177
+ </div>
148
178
  </ReactFlowProvider>,
149
179
  elem
150
180
  )}
@@ -3,6 +3,7 @@ import Schema from '@components/MDX/Schema';
3
3
  import File from '@components/MDX/File';
4
4
  import Accordion from '@components/MDX/Accordion/Accordion.astro';
5
5
  import AccordionGroup from '@components/MDX/Accordion/AccordionGroup.astro';
6
+ import Flow from '@components/MDX/Flow/Flow.astro';
6
7
  import Admonition from '@components/MDX/Admonition';
7
8
  import OpenAPI from '@components/MDX/OpenAPI/OpenAPI';
8
9
 
@@ -14,6 +15,7 @@ const components = (props: any) => {
14
15
  return {
15
16
  Accordion,
16
17
  AccordionGroup,
18
+ Flow,
17
19
  Admonition: (mdxProp: any) => <Admonition {...mdxProp} {...props} />,
18
20
  File: (mdxProp: any) => File({ ...props, ...mdxProp }),
19
21
  NodeGraph: (mdxProp: any) => NodeGraphPortal({ ...props.data, ...mdxProp }),
@@ -5,6 +5,7 @@ import Footer from '@layouts/Footer.astro';
5
5
 
6
6
  import components from '@components/MDX/components';
7
7
  import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
8
+ import SchemaViewer from '@components/MDX/SchemaViewer/SchemaViewer.astro';
8
9
 
9
10
  // SideBars
10
11
  import ServiceSideBar from '@components/SideBars/ServiceSideBar.astro';
@@ -17,7 +18,7 @@ import { EnvelopeIcon, PencilIcon, QueueListIcon, RectangleGroupIcon, ServerIcon
17
18
  import { getDomains } from '@utils/domains/domains';
18
19
  import DomainSideBar from '@components/SideBars/DomainSideBar.astro';
19
20
  import type { CollectionTypes } from '@types';
20
- import SchemaViewer from '@components/MDX/SchemaViewer/SchemaViewer.astro';
21
+
21
22
  import { buildUrl } from '@utils/url-builder';
22
23
  import { getFlows } from '@utils/flows/flows';
23
24
 
@@ -1,5 +1,5 @@
1
1
  import { getVersionForCollectionItem, getVersions } from '@utils/collections/util';
2
- import { getVersion } from '@utils/services/services';
2
+ import { getVersionFromCollection } from '@utils/versions/versions';
3
3
  import { getCollection } from 'astro:content';
4
4
  import type { CollectionEntry } from 'astro:content';
5
5
  import path from 'path';
@@ -31,7 +31,7 @@ export const getFlows = async ({ getAllVersions = true }: Props = {}): Promise<F
31
31
 
32
32
  const hydrateSteps = steps.map((step) => {
33
33
  if (!step.message) return { ...flow, data: { ...flow.data, type: 'node' } };
34
- const message = getVersion(allMessages, step.message.id, step.message.version);
34
+ const message = getVersionFromCollection(allMessages, step.message.id, step.message.version);
35
35
  return {
36
36
  ...step,
37
37
  type: 'message',
@@ -1,9 +1,9 @@
1
1
  import { getCollection, type CollectionEntry } from 'astro:content';
2
2
  import dagre from 'dagre';
3
- import { getVersion } from '../services/services';
4
3
  import { createDagreGraph, calculatedNodes } from '@utils/node-graph-utils/utils';
5
4
  import { MarkerType } from 'reactflow';
6
5
  import type { Node as NodeType } from 'reactflow';
6
+ import { getVersionFromCollection } from '@utils/versions/versions';
7
7
 
8
8
  type DagreGraph = any;
9
9
 
@@ -27,7 +27,7 @@ const getServiceNode = (step: any, services: CollectionEntry<'services'>[]) => {
27
27
  };
28
28
 
29
29
  const getMessageNode = (step: any, messages: CollectionEntry<'events' | 'commands'>[]) => {
30
- const messagesForVersion = getVersion(messages, step.message.id, step.message.version);
30
+ const messagesForVersion = getVersionFromCollection(messages, step.message.id, step.message.version);
31
31
  const message = messagesForVersion[0];
32
32
  return {
33
33
  ...step,
@@ -1,9 +1,9 @@
1
1
  // import { getColor } from '@utils/colors';
2
2
  import { getCollection, type CollectionEntry } from 'astro:content';
3
3
  import dagre from 'dagre';
4
- import { getVersion } from './services';
5
4
  import { createDagreGraph, generateIdForNode, generatedIdForEdge, calculatedNodes } from '@utils/node-graph-utils/utils';
6
5
  import { MarkerType } from 'reactflow';
6
+ import { getVersionFromCollection } from '@utils/versions/versions';
7
7
 
8
8
  type DagreGraph = any;
9
9
 
@@ -41,12 +41,12 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
41
41
  const messages = [...events, ...commands];
42
42
 
43
43
  const receivesHydrated = receivesRaw
44
- .map((message) => getVersion(messages, message.id, message.version))
44
+ .map((message) => getVersionFromCollection(messages, message.id, message.version))
45
45
  .flat()
46
46
  .filter((e) => e !== undefined);
47
47
 
48
48
  const sendsHydrated = sendsRaw
49
- .map((message) => getVersion(messages, message.id, message.version))
49
+ .map((message) => getVersionFromCollection(messages, message.id, message.version))
50
50
  .flat()
51
51
  .filter((e) => e !== undefined);
52
52
 
@@ -1,36 +1,13 @@
1
1
  import { getVersionForCollectionItem } from '@utils/collections/util';
2
+ import { getVersionFromCollection } from '@utils/versions/versions';
2
3
  import { getCollection } from 'astro:content';
3
4
  import type { CollectionEntry } from 'astro:content';
4
5
  import path from 'path';
5
- import { satisfies, validRange } from 'semver';
6
6
 
7
7
  const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
8
8
 
9
9
  export type Service = CollectionEntry<'services'>;
10
10
 
11
- export const getVersion = (
12
- collection: CollectionEntry<'events' | 'commands'>[],
13
- id: string,
14
- version?: string
15
- ): CollectionEntry<'events' | 'commands'>[] => {
16
- const data = collection;
17
- const semverRange = validRange(version);
18
-
19
- if (semverRange) {
20
- return data.filter((msg) => msg.data.id == id).filter((msg) => satisfies(msg.data.version, semverRange));
21
- }
22
-
23
- const filteredEvents = data.filter((event) => event.data.id === id);
24
-
25
- // Order by version
26
- const sorted = filteredEvents.sort((a, b) => {
27
- return a.data.version.localeCompare(b.data.version);
28
- });
29
-
30
- // latest version
31
- return [sorted[sorted.length - 1]];
32
- };
33
-
34
11
  interface Props {
35
12
  getAllVersions?: boolean;
36
13
  }
@@ -53,12 +30,12 @@ export const getServices = async ({ getAllVersions = true }: Props = {}): Promis
53
30
  const receivesMessages = service.data.receives || [];
54
31
 
55
32
  const sends = sendsMessages
56
- .map((message) => getVersion(allMessages, message.id, message.version))
33
+ .map((message) => getVersionFromCollection(allMessages, message.id, message.version))
57
34
  .flat()
58
35
  .filter((e) => e !== undefined);
59
36
 
60
37
  const receives = receivesMessages
61
- .map((message) => getVersion(allMessages, message.id, message.version))
38
+ .map((message) => getVersionFromCollection(allMessages, message.id, message.version))
62
39
  .flat()
63
40
  .filter((e) => e !== undefined);
64
41
 
@@ -0,0 +1,26 @@
1
+ import type { CollectionTypes } from '@types';
2
+ import type { CollectionEntry } from 'astro:content';
3
+ import { satisfies, validRange } from 'semver';
4
+
5
+ export const getVersionFromCollection = (
6
+ collection: CollectionEntry<CollectionTypes>[],
7
+ id: string,
8
+ version?: string
9
+ ): CollectionEntry<CollectionTypes>[] => {
10
+ const data = collection;
11
+ const semverRange = validRange(version);
12
+
13
+ if (semverRange) {
14
+ return data.filter((msg) => msg.data.id == id).filter((msg) => satisfies(msg.data.version, semverRange));
15
+ }
16
+
17
+ const filteredEvents = data.filter((event) => event.data.id === id);
18
+
19
+ // Order by version
20
+ const sorted = filteredEvents.sort((a, b) => {
21
+ return a.data.version.localeCompare(b.data.version);
22
+ });
23
+
24
+ // latest version
25
+ return [sorted[sorted.length - 1]];
26
+ };