@eventcatalog/core 2.3.4 → 2.5.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/CHANGELOG.md +19 -0
- package/README.md +7 -0
- package/bin/dist/eventcatalog.cjs +5 -4
- package/bin/dist/eventcatalog.js +5 -4
- package/package.json +9 -6
- package/scripts/catalog-to-astro-content-directory.js +32 -1
- package/scripts/default-files-for-collections/flows.md +11 -0
- package/scripts/default-files-for-collections/pages.md +1 -0
- package/scripts/watcher.js +1 -2
- package/src/components/DocsNavigation.astro +5 -1
- package/src/components/MDX/NodeGraph/NodeGraph.astro +12 -0
- package/src/components/MDX/NodeGraph/NodeGraph.tsx +16 -4
- package/src/components/MDX/NodeGraph/Nodes/ExternalSystem.tsx +79 -0
- package/src/components/MDX/NodeGraph/Nodes/Service.tsx +0 -12
- package/src/components/MDX/NodeGraph/Nodes/Step.tsx +69 -0
- package/src/components/MDX/NodeGraph/Nodes/User.tsx +79 -0
- package/src/components/SideBars/DomainSideBar.astro +1 -1
- package/src/components/Tables/columns/FlowTableColumns.tsx +82 -0
- package/src/components/Tables/columns/index.tsx +3 -0
- package/src/content/config.ts +65 -5
- package/src/layouts/DiscoverLayout.astro +11 -1
- package/src/layouts/VisualiserLayout.astro +33 -22
- package/src/pages/discover/[type]/index.astro +3 -0
- package/src/pages/docs/[type]/[id]/[version]/index.astro +10 -2
- package/src/pages/docs/teams/[id]/index.astro +14 -0
- package/src/pages/docs/users/[id]/index.astro +23 -4
- package/src/pages/visualiser/[type]/[id]/[version]/index.astro +9 -2
- package/src/types/index.ts +1 -1
- package/src/utils/collections/util.ts +22 -0
- package/src/utils/commands/node-graph.ts +13 -2
- package/src/utils/commands.ts +5 -4
- package/src/utils/config/catalog.ts +1 -0
- package/src/utils/domains/domains.ts +3 -5
- package/src/utils/domains/node-graph.ts +28 -9
- package/src/utils/events/node-graph.ts +13 -2
- package/src/utils/events.ts +3 -2
- package/src/utils/flows/flows.ts +59 -0
- package/src/utils/flows/node-graph.ts +153 -0
- package/src/utils/services/node-graph.ts +17 -9
- package/src/utils/services/services.ts +16 -16
- package/src/utils/teams.ts +7 -1
- package/src/utils/users.ts +8 -0
- package/tailwind.config.mjs +1 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
// import { getColor } from '@utils/colors';
|
|
2
1
|
import { getCollection } from 'astro:content';
|
|
3
2
|
import dagre from 'dagre';
|
|
4
3
|
import { getNodesAndEdges as getServicesNodeAndEdges } from '../services/node-graph';
|
|
4
|
+
import merge from 'lodash.merge';
|
|
5
|
+
import { getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
|
|
5
6
|
|
|
6
7
|
type DagreGraph = any;
|
|
7
8
|
|
|
8
9
|
// Creates a new dagre graph
|
|
9
10
|
export const getDagreGraph = () => {
|
|
10
11
|
const graph = new dagre.graphlib.Graph({ compound: true });
|
|
11
|
-
graph.setGraph({ rankdir: 'LR', ranksep: 200, nodesep:
|
|
12
|
+
graph.setGraph({ rankdir: 'LR', ranksep: 200, nodesep: 100 });
|
|
12
13
|
graph.setDefaultEdgeLabel(() => ({}));
|
|
13
14
|
return graph;
|
|
14
15
|
};
|
|
@@ -22,8 +23,8 @@ interface Props {
|
|
|
22
23
|
|
|
23
24
|
export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simple' }: Props) => {
|
|
24
25
|
const flow = defaultFlow || getDagreGraph();
|
|
25
|
-
let nodes =
|
|
26
|
-
edges =
|
|
26
|
+
let nodes = new Map(),
|
|
27
|
+
edges = new Map();
|
|
27
28
|
|
|
28
29
|
const domains = await getCollection('domains');
|
|
29
30
|
|
|
@@ -39,9 +40,16 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
|
|
|
39
40
|
|
|
40
41
|
const rawServices = domain?.data.services || [];
|
|
41
42
|
|
|
43
|
+
const servicesCollection = await getCollection('services');
|
|
44
|
+
|
|
45
|
+
const domainServicesWithVersion = rawServices
|
|
46
|
+
.map((service) => getItemsFromCollectionByIdAndSemverOrLatest(servicesCollection, service.id, service.version))
|
|
47
|
+
.flat()
|
|
48
|
+
.map((svc) => ({ id: svc.data.id, version: svc.data.version }));
|
|
49
|
+
|
|
42
50
|
// Get all the nodes for everyhing
|
|
43
51
|
|
|
44
|
-
for (const service of
|
|
52
|
+
for (const service of domainServicesWithVersion) {
|
|
45
53
|
const { nodes: serviceNodes, edges: serviceEdges } = await getServicesNodeAndEdges({
|
|
46
54
|
id: service.id,
|
|
47
55
|
version: service.version,
|
|
@@ -49,12 +57,23 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
|
|
|
49
57
|
mode,
|
|
50
58
|
renderAllEdges: true,
|
|
51
59
|
});
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
serviceNodes.forEach((n) => {
|
|
61
|
+
/**
|
|
62
|
+
* A message could be sent by one service and received by another service on the same domain.
|
|
63
|
+
* So, we need deep merge the message to keep the `showSource` and `showTarget` as true.
|
|
64
|
+
*
|
|
65
|
+
* Let's see an example:
|
|
66
|
+
* Take an `OrderPlaced` event sent by the `OrderService` `{ showSource: true }` and
|
|
67
|
+
* received by `PaymentService` `{ showTarget: true }`.
|
|
68
|
+
*/
|
|
69
|
+
nodes.set(n.id, nodes.has(n.id) ? merge(nodes.get(n.id), n) : n);
|
|
70
|
+
});
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
serviceEdges.forEach((e) => edges.set(e.id, e));
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
return {
|
|
57
|
-
nodes: nodes,
|
|
58
|
-
edges: edges,
|
|
76
|
+
nodes: [...nodes.values()],
|
|
77
|
+
edges: [...edges.values()],
|
|
59
78
|
};
|
|
60
79
|
};
|
|
@@ -3,6 +3,7 @@ import { getEvents } from '@utils/events';
|
|
|
3
3
|
import type { CollectionEntry } from 'astro:content';
|
|
4
4
|
import dagre from 'dagre';
|
|
5
5
|
import { calculatedNodes, createDagreGraph, generatedIdForEdge, generateIdForNode } from '../node-graph-utils/utils';
|
|
6
|
+
import { MarkerType } from 'reactflow';
|
|
6
7
|
|
|
7
8
|
type DagreGraph = any;
|
|
8
9
|
|
|
@@ -51,7 +52,12 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
|
|
|
51
52
|
label: 'publishes event',
|
|
52
53
|
animated: false,
|
|
53
54
|
markerEnd: {
|
|
54
|
-
type:
|
|
55
|
+
type: MarkerType.ArrowClosed,
|
|
56
|
+
width: 40,
|
|
57
|
+
height: 40,
|
|
58
|
+
},
|
|
59
|
+
style: {
|
|
60
|
+
strokeWidth: 1,
|
|
55
61
|
},
|
|
56
62
|
});
|
|
57
63
|
});
|
|
@@ -85,7 +91,12 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
|
|
|
85
91
|
label: 'subscribed by',
|
|
86
92
|
animated: false,
|
|
87
93
|
markerEnd: {
|
|
88
|
-
type:
|
|
94
|
+
type: MarkerType.ArrowClosed,
|
|
95
|
+
width: 40,
|
|
96
|
+
height: 40,
|
|
97
|
+
},
|
|
98
|
+
style: {
|
|
99
|
+
strokeWidth: 1,
|
|
89
100
|
},
|
|
90
101
|
});
|
|
91
102
|
});
|
package/src/utils/events.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { getCollection } from 'astro:content';
|
|
|
2
2
|
import type { CollectionEntry } from 'astro:content';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { getVersionForCollectionItem } from './collections/util';
|
|
5
|
+
import { satisfies } from 'semver';
|
|
5
6
|
|
|
6
7
|
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
7
8
|
|
|
@@ -30,14 +31,14 @@ export const getEvents = async ({ getAllVersions = true }: Props = {}): Promise<
|
|
|
30
31
|
const producers = services.filter((service) => {
|
|
31
32
|
if (!service.data.sends) return false;
|
|
32
33
|
return service.data.sends.find((item) => {
|
|
33
|
-
return item.id === event.data.id &&
|
|
34
|
+
return item.id === event.data.id && satisfies(event.data.version, item.version);
|
|
34
35
|
});
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
const consumers = services.filter((service) => {
|
|
38
39
|
if (!service.data.receives) return false;
|
|
39
40
|
return service.data.receives.find((item) => {
|
|
40
|
-
return item.id === event.data.id &&
|
|
41
|
+
return item.id === event.data.id && satisfies(event.data.version, item.version);
|
|
41
42
|
|
|
42
43
|
// If no version has been found, then get try find the latest one
|
|
43
44
|
// return item.id == event.data.id
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getVersionForCollectionItem, getVersions } from '@utils/collections/util';
|
|
2
|
+
import { getVersion } from '@utils/services/services';
|
|
3
|
+
import { getCollection } from 'astro:content';
|
|
4
|
+
import type { CollectionEntry } from 'astro:content';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
8
|
+
|
|
9
|
+
export type Flow = CollectionEntry<'flows'>;
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
getAllVersions?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getFlows = async ({ getAllVersions = true }: Props = {}): Promise<Flow[]> => {
|
|
16
|
+
// Get flows that are not versioned
|
|
17
|
+
const flows = await getCollection('flows', (flow) => {
|
|
18
|
+
return (getAllVersions || !flow.slug.includes('versioned')) && flow.data.hidden !== true;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const events = await getCollection('events');
|
|
22
|
+
const commands = await getCollection('commands');
|
|
23
|
+
|
|
24
|
+
const allMessages = [...events, ...commands];
|
|
25
|
+
|
|
26
|
+
// @ts-ignore // TODO: Fix this type
|
|
27
|
+
return flows.map((flow) => {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
const { latestVersion, versions } = getVersionForCollectionItem(flow, flows);
|
|
30
|
+
const steps = flow.data.steps || [];
|
|
31
|
+
|
|
32
|
+
const hydrateSteps = steps.map((step) => {
|
|
33
|
+
if (!step.message) return { ...flow, data: { ...flow.data, type: 'node' } };
|
|
34
|
+
const message = getVersion(allMessages, step.message.id, step.message.version);
|
|
35
|
+
return {
|
|
36
|
+
...step,
|
|
37
|
+
type: 'message',
|
|
38
|
+
message: message,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
...flow,
|
|
44
|
+
data: {
|
|
45
|
+
...flow.data,
|
|
46
|
+
steps: hydrateSteps,
|
|
47
|
+
versions,
|
|
48
|
+
latestVersion,
|
|
49
|
+
},
|
|
50
|
+
catalog: {
|
|
51
|
+
path: path.join(flow.collection, flow.id.replace('/index.mdx', '')),
|
|
52
|
+
absoluteFilePath: path.join(PROJECT_DIR, flow.collection, flow.id.replace('/index.mdx', '/index.md')),
|
|
53
|
+
filePath: path.join(process.cwd(), 'src', 'catalog-files', flow.collection, flow.id.replace('/index.mdx', '')),
|
|
54
|
+
publicPath: path.join('/generated', flow.collection, flow.id.replace('/index.mdx', '')),
|
|
55
|
+
type: 'flow',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
2
|
+
import dagre from 'dagre';
|
|
3
|
+
import { getVersion } from '../services/services';
|
|
4
|
+
import { createDagreGraph, calculatedNodes } from '@utils/node-graph-utils/utils';
|
|
5
|
+
import { MarkerType } from 'reactflow';
|
|
6
|
+
import type { Node as NodeType } from 'reactflow';
|
|
7
|
+
|
|
8
|
+
type DagreGraph = any;
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
id: string;
|
|
12
|
+
version: string;
|
|
13
|
+
defaultFlow?: DagreGraph;
|
|
14
|
+
mode?: 'simple' | 'full';
|
|
15
|
+
renderAllEdges?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const getServiceNode = (step: any, services: CollectionEntry<'services'>[]) => {
|
|
19
|
+
const service = services.find(
|
|
20
|
+
(service) => service.data.id === step.service.id && service.data.version === step.service.version
|
|
21
|
+
);
|
|
22
|
+
return {
|
|
23
|
+
...step,
|
|
24
|
+
type: service ? service.collection : 'step',
|
|
25
|
+
service,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const getMessageNode = (step: any, messages: CollectionEntry<'events' | 'commands'>[]) => {
|
|
30
|
+
const messagesForVersion = getVersion(messages, step.message.id, step.message.version);
|
|
31
|
+
const message = messagesForVersion[0];
|
|
32
|
+
return {
|
|
33
|
+
...step,
|
|
34
|
+
type: message ? message.collection : 'step',
|
|
35
|
+
message,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simple', renderAllEdges = false }: Props) => {
|
|
40
|
+
const graph = defaultFlow || createDagreGraph({ ranksep: 360, nodesep: 200 });
|
|
41
|
+
const nodes = [] as any,
|
|
42
|
+
edges = [] as any;
|
|
43
|
+
|
|
44
|
+
const flows = await getCollection('flows');
|
|
45
|
+
const flow = flows.find((flow) => flow.data.id === id && flow.data.version === version);
|
|
46
|
+
|
|
47
|
+
// Nothing found...
|
|
48
|
+
if (!flow) {
|
|
49
|
+
return {
|
|
50
|
+
nodes: [],
|
|
51
|
+
edges: [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const events = await getCollection('events');
|
|
56
|
+
const commands = await getCollection('commands');
|
|
57
|
+
const services = await getCollection('services');
|
|
58
|
+
|
|
59
|
+
const messages = [...events, ...commands];
|
|
60
|
+
|
|
61
|
+
const steps = flow?.data.steps || [];
|
|
62
|
+
|
|
63
|
+
// Hydrate the steps with information they may need.
|
|
64
|
+
const hydratedSteps = steps.map((step: any) => {
|
|
65
|
+
if (step.service) return getServiceNode(step, services);
|
|
66
|
+
if (step.message) return getMessageNode(step, messages);
|
|
67
|
+
if (step.actor) return { ...step, type: 'actor', actor: step.actor };
|
|
68
|
+
if (step.externalSystem) return { ...step, type: 'externalSystem', externalSystem: step.externalSystem };
|
|
69
|
+
return { ...step, type: 'step' };
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Create nodes
|
|
73
|
+
hydratedSteps.forEach((step, index: number) => {
|
|
74
|
+
const node = {
|
|
75
|
+
id: `step-${step.id}`,
|
|
76
|
+
sourcePosition: 'right',
|
|
77
|
+
targetPosition: 'left',
|
|
78
|
+
data: {
|
|
79
|
+
mode,
|
|
80
|
+
step: step,
|
|
81
|
+
showTarget: true,
|
|
82
|
+
showSource: true,
|
|
83
|
+
},
|
|
84
|
+
position: { x: 250, y: index * 150 },
|
|
85
|
+
type: step.type,
|
|
86
|
+
} as NodeType;
|
|
87
|
+
|
|
88
|
+
if (step.service) node.data.service = step.service;
|
|
89
|
+
if (step.message) node.data.message = step.message;
|
|
90
|
+
if (step.actor) node.data.actor = step.actor;
|
|
91
|
+
if (step.externalSystem) node.data.externalSystem = step.externalSystem;
|
|
92
|
+
|
|
93
|
+
nodes.push(node);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Create Edges
|
|
97
|
+
hydratedSteps.forEach((step, index: number) => {
|
|
98
|
+
let paths = step.next_steps || [];
|
|
99
|
+
|
|
100
|
+
if (step.next_step) {
|
|
101
|
+
// If its a string or number
|
|
102
|
+
if (!step.next_step?.id) {
|
|
103
|
+
paths = [{ id: step.next_step }];
|
|
104
|
+
} else {
|
|
105
|
+
paths = [step.next_step];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
paths = paths.map((path: any) => {
|
|
110
|
+
if (typeof path === 'string') {
|
|
111
|
+
return { id: path };
|
|
112
|
+
}
|
|
113
|
+
return path;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
paths.forEach((path: any) => {
|
|
117
|
+
edges.push({
|
|
118
|
+
id: `step-${step.id}-step-${path.id}`,
|
|
119
|
+
source: `step-${step.id}`,
|
|
120
|
+
target: `step-${path.id}`,
|
|
121
|
+
type: 'smoothstep',
|
|
122
|
+
label: path.label,
|
|
123
|
+
animated: true,
|
|
124
|
+
markerEnd: {
|
|
125
|
+
type: MarkerType.ArrowClosed,
|
|
126
|
+
width: 20,
|
|
127
|
+
height: 20,
|
|
128
|
+
color: '#acacac',
|
|
129
|
+
},
|
|
130
|
+
style: {
|
|
131
|
+
strokeWidth: 2,
|
|
132
|
+
stroke: '#acacac',
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
nodes.forEach((node: any) => {
|
|
139
|
+
graph.setNode(node.id, { width: 150, height: 100 });
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
edges.forEach((edge: any) => {
|
|
143
|
+
graph.setEdge(edge.source, edge.target);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Render the diagram in memory getting hte X and Y
|
|
147
|
+
dagre.layout(graph);
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
nodes: calculatedNodes(graph, nodes),
|
|
151
|
+
edges: edges,
|
|
152
|
+
};
|
|
153
|
+
};
|
|
@@ -3,6 +3,7 @@ import { getCollection, type CollectionEntry } from 'astro:content';
|
|
|
3
3
|
import dagre from 'dagre';
|
|
4
4
|
import { getVersion } from './services';
|
|
5
5
|
import { createDagreGraph, generateIdForNode, generatedIdForEdge, calculatedNodes } from '@utils/node-graph-utils/utils';
|
|
6
|
+
import { MarkerType } from 'reactflow';
|
|
6
7
|
|
|
7
8
|
type DagreGraph = any;
|
|
8
9
|
|
|
@@ -40,16 +41,13 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
40
41
|
const messages = [...events, ...commands];
|
|
41
42
|
|
|
42
43
|
const receivesHydrated = receivesRaw
|
|
43
|
-
.map((message) =>
|
|
44
|
-
|
|
45
|
-
})
|
|
44
|
+
.map((message) => getVersion(messages, message.id, message.version))
|
|
45
|
+
.flat()
|
|
46
46
|
.filter((e) => e !== undefined);
|
|
47
47
|
|
|
48
48
|
const sendsHydrated = sendsRaw
|
|
49
|
-
.map((message) =>
|
|
50
|
-
|
|
51
|
-
// return messages.find((message) => message.data.id === messageId);
|
|
52
|
-
})
|
|
49
|
+
.map((message) => getVersion(messages, message.id, message.version))
|
|
50
|
+
.flat()
|
|
53
51
|
.filter((e) => e !== undefined);
|
|
54
52
|
|
|
55
53
|
const receives = (receivesHydrated as CollectionEntry<'events' | 'commands'>[]) || [];
|
|
@@ -76,7 +74,12 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
76
74
|
label: receive?.collection === 'events' ? 'receives event' : 'accepts',
|
|
77
75
|
animated: false,
|
|
78
76
|
markerEnd: {
|
|
79
|
-
type:
|
|
77
|
+
type: MarkerType.ArrowClosed,
|
|
78
|
+
width: 40,
|
|
79
|
+
height: 40,
|
|
80
|
+
},
|
|
81
|
+
style: {
|
|
82
|
+
strokeWidth: 1,
|
|
80
83
|
},
|
|
81
84
|
});
|
|
82
85
|
});
|
|
@@ -110,7 +113,12 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
110
113
|
label: send?.collection === 'events' ? 'publishes event' : 'invokes command',
|
|
111
114
|
animated: false,
|
|
112
115
|
markerEnd: {
|
|
113
|
-
type:
|
|
116
|
+
type: MarkerType.ArrowClosed,
|
|
117
|
+
width: 40,
|
|
118
|
+
height: 40,
|
|
119
|
+
},
|
|
120
|
+
style: {
|
|
121
|
+
strokeWidth: 1,
|
|
114
122
|
},
|
|
115
123
|
});
|
|
116
124
|
});
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import { getVersionForCollectionItem
|
|
1
|
+
import { getVersionForCollectionItem } from '@utils/collections/util';
|
|
2
2
|
import { getCollection } from 'astro:content';
|
|
3
3
|
import type { CollectionEntry } from 'astro:content';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
import { satisfies, validRange } from 'semver';
|
|
5
6
|
|
|
6
7
|
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
7
8
|
|
|
8
9
|
export type Service = CollectionEntry<'services'>;
|
|
9
10
|
|
|
10
|
-
export const getVersion = (
|
|
11
|
+
export const getVersion = (
|
|
12
|
+
collection: CollectionEntry<'events' | 'commands'>[],
|
|
13
|
+
id: string,
|
|
14
|
+
version?: string
|
|
15
|
+
): CollectionEntry<'events' | 'commands'>[] => {
|
|
11
16
|
const data = collection;
|
|
12
|
-
|
|
13
|
-
|
|
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));
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
const filteredEvents = data.filter((event) => event.data.id === id);
|
|
@@ -21,7 +28,7 @@ export const getVersion = (collection: CollectionEntry<'events' | 'commands'>[],
|
|
|
21
28
|
});
|
|
22
29
|
|
|
23
30
|
// latest version
|
|
24
|
-
return sorted[sorted.length - 1];
|
|
31
|
+
return [sorted[sorted.length - 1]];
|
|
25
32
|
};
|
|
26
33
|
|
|
27
34
|
interface Props {
|
|
@@ -42,24 +49,17 @@ export const getServices = async ({ getAllVersions = true }: Props = {}): Promis
|
|
|
42
49
|
return services.map((service) => {
|
|
43
50
|
const { latestVersion, versions } = getVersionForCollectionItem(service, services);
|
|
44
51
|
|
|
45
|
-
// const receives = service.data.receives || [];
|
|
46
52
|
const sendsMessages = service.data.sends || [];
|
|
47
53
|
const receivesMessages = service.data.receives || [];
|
|
48
54
|
|
|
49
55
|
const sends = sendsMessages
|
|
50
|
-
.map((message) =>
|
|
51
|
-
|
|
52
|
-
// const event = allMessages.find((_message) => _message.data.id === message.id && _message.data.version === message.version);
|
|
53
|
-
return event;
|
|
54
|
-
})
|
|
56
|
+
.map((message) => getVersion(allMessages, message.id, message.version))
|
|
57
|
+
.flat()
|
|
55
58
|
.filter((e) => e !== undefined);
|
|
56
59
|
|
|
57
60
|
const receives = receivesMessages
|
|
58
|
-
.map((message) =>
|
|
59
|
-
|
|
60
|
-
// const event = allMessages.find((_message) => _message.data.id === message.id && _message.data.version === message.version);
|
|
61
|
-
return event;
|
|
62
|
-
})
|
|
61
|
+
.map((message) => getVersion(allMessages, message.id, message.version))
|
|
62
|
+
.flat()
|
|
63
63
|
.filter((e) => e !== undefined);
|
|
64
64
|
|
|
65
65
|
return {
|
package/src/utils/teams.ts
CHANGED
|
@@ -9,7 +9,8 @@ export const getTeams = async (): Promise<Team[]> => {
|
|
|
9
9
|
const teams = await getCollection('teams', (team) => {
|
|
10
10
|
return team.data.hidden !== true;
|
|
11
11
|
});
|
|
12
|
-
|
|
12
|
+
// What do they own?
|
|
13
|
+
const domains = await getCollection('domains');
|
|
13
14
|
// What do they own?
|
|
14
15
|
const services = await getCollection('services');
|
|
15
16
|
// What do they own?
|
|
@@ -17,6 +18,10 @@ export const getTeams = async (): Promise<Team[]> => {
|
|
|
17
18
|
const commands = await getCollection('commands');
|
|
18
19
|
|
|
19
20
|
return teams.map((team) => {
|
|
21
|
+
const ownedDomains = domains.filter((domain) => {
|
|
22
|
+
return domain.data.owners?.find((owner) => owner.slug === team.data.id);
|
|
23
|
+
});
|
|
24
|
+
|
|
20
25
|
const ownedServices = services.filter((service) => {
|
|
21
26
|
return service.data.owners?.find((owner) => owner.slug === team.data.id);
|
|
22
27
|
});
|
|
@@ -33,6 +38,7 @@ export const getTeams = async (): Promise<Team[]> => {
|
|
|
33
38
|
...team,
|
|
34
39
|
data: {
|
|
35
40
|
...team.data,
|
|
41
|
+
ownedDomains,
|
|
36
42
|
ownedServices,
|
|
37
43
|
ownedCommands,
|
|
38
44
|
ownedEvents,
|
package/src/utils/users.ts
CHANGED
|
@@ -10,6 +10,9 @@ export const getUsers = async (): Promise<User[]> => {
|
|
|
10
10
|
return user.data.hidden !== true;
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
+
// What do they own?
|
|
14
|
+
const domains = await getCollection('domains');
|
|
15
|
+
|
|
13
16
|
// What do they own?
|
|
14
17
|
const services = await getCollection('services');
|
|
15
18
|
|
|
@@ -24,6 +27,10 @@ export const getUsers = async (): Promise<User[]> => {
|
|
|
24
27
|
});
|
|
25
28
|
|
|
26
29
|
return users.map((user) => {
|
|
30
|
+
const ownedDomains = domains.filter((domain) => {
|
|
31
|
+
return domain.data.owners?.find((owner) => owner.slug === user.data.id);
|
|
32
|
+
});
|
|
33
|
+
|
|
27
34
|
const ownedServices = services.filter((service) => {
|
|
28
35
|
return service.data.owners?.find((owner) => owner.slug === user.data.id);
|
|
29
36
|
});
|
|
@@ -44,6 +51,7 @@ export const getUsers = async (): Promise<User[]> => {
|
|
|
44
51
|
...user,
|
|
45
52
|
data: {
|
|
46
53
|
...user.data,
|
|
54
|
+
ownedDomains,
|
|
47
55
|
ownedServices,
|
|
48
56
|
ownedEvents,
|
|
49
57
|
ownedCommands,
|
package/tailwind.config.mjs
CHANGED