@eventcatalog/core 4.10.15 → 4.11.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/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/astro-output.cjs +60 -1
- package/dist/astro-output.js +1 -1
- package/dist/{chunk-U52FCZQ6.js → chunk-2YJRF4ZX.js} +1 -1
- package/dist/chunk-634NFV5U.js +75 -0
- package/dist/{chunk-I6HUOX4R.js → chunk-AXDNSGAN.js} +1 -1
- package/dist/chunk-DHH5U5PF.js +53 -0
- package/dist/{chunk-A4JRWRCV.js → chunk-DSCIWCX2.js} +1 -1
- package/dist/chunk-FWXEV4LF.js +19 -0
- package/dist/{chunk-Q2ATWE7N.js → chunk-GZVDXCYF.js} +1 -1
- package/dist/{chunk-7LWOCX4R.js → chunk-RYNPEIHQ.js} +1 -1
- package/dist/{chunk-HBVTU6ZP.js → chunk-YYVW4DCO.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/copy-core.cjs +88 -0
- package/dist/copy-core.d.cts +4 -0
- package/dist/copy-core.d.ts +4 -0
- package/dist/copy-core.js +8 -0
- package/dist/eventcatalog.cjs +234 -115
- package/dist/eventcatalog.js +36 -30
- package/dist/federation/federate.js +3 -3
- package/dist/federation/source-provider.js +2 -2
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/update-check.cjs +44 -0
- package/dist/update-check.d.cts +18 -0
- package/dist/update-check.d.ts +18 -0
- package/dist/update-check.js +8 -0
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/astro.config.mjs +8 -1
- package/eventcatalog/public/icons/languages/android.svg +1 -0
- package/eventcatalog/public/icons/languages/angular.svg +1 -0
- package/eventcatalog/public/icons/languages/apple.svg +1 -0
- package/eventcatalog/public/icons/languages/arduino.svg +1 -0
- package/eventcatalog/public/icons/languages/bash.svg +1 -0
- package/eventcatalog/public/icons/languages/bun.svg +1 -0
- package/eventcatalog/public/icons/languages/c.svg +1 -0
- package/eventcatalog/public/icons/languages/clojure.svg +1 -0
- package/eventcatalog/public/icons/languages/cpp.svg +1 -0
- package/eventcatalog/public/icons/languages/crystal.svg +1 -0
- package/eventcatalog/public/icons/languages/csharp.svg +1 -0
- package/eventcatalog/public/icons/languages/css.svg +1 -0
- package/eventcatalog/public/icons/languages/curl.svg +1 -0
- package/eventcatalog/public/icons/languages/dart.svg +1 -0
- package/eventcatalog/public/icons/languages/deno.svg +1 -0
- package/eventcatalog/public/icons/languages/docker.svg +1 -0
- package/eventcatalog/public/icons/languages/elm.svg +1 -0
- package/eventcatalog/public/icons/languages/erlang.svg +1 -0
- package/eventcatalog/public/icons/languages/flutter.svg +1 -0
- package/eventcatalog/public/icons/languages/fortran.svg +1 -0
- package/eventcatalog/public/icons/languages/fsharp.svg +1 -0
- package/eventcatalog/public/icons/languages/git.svg +1 -0
- package/eventcatalog/public/icons/languages/gradle.svg +1 -0
- package/eventcatalog/public/icons/languages/graphql.svg +1 -0
- package/eventcatalog/public/icons/languages/grpc.svg +1 -0
- package/eventcatalog/public/icons/languages/haskell.svg +1 -0
- package/eventcatalog/public/icons/languages/hasura.svg +1 -0
- package/eventcatalog/public/icons/languages/html.svg +1 -0
- package/eventcatalog/public/icons/languages/httpie.svg +1 -0
- package/eventcatalog/public/icons/languages/javascript.svg +1 -0
- package/eventcatalog/public/icons/languages/json-schema.svg +1 -0
- package/eventcatalog/public/icons/languages/json.svg +1 -0
- package/eventcatalog/public/icons/languages/julia.svg +1 -0
- package/eventcatalog/public/icons/languages/jupyter.svg +1 -0
- package/eventcatalog/public/icons/languages/kafka.svg +1 -0
- package/eventcatalog/public/icons/languages/kotlin.svg +1 -0
- package/eventcatalog/public/icons/languages/lua.svg +1 -0
- package/eventcatalog/public/icons/languages/markdown.svg +1 -0
- package/eventcatalog/public/icons/languages/maven.svg +1 -0
- package/eventcatalog/public/icons/languages/mongodb.svg +1 -0
- package/eventcatalog/public/icons/languages/mysql.svg +1 -0
- package/eventcatalog/public/icons/languages/nginx.svg +1 -0
- package/eventcatalog/public/icons/languages/nim.svg +1 -0
- package/eventcatalog/public/icons/languages/ocaml.svg +1 -0
- package/eventcatalog/public/icons/languages/perl.svg +1 -0
- package/eventcatalog/public/icons/languages/php.svg +1 -0
- package/eventcatalog/public/icons/languages/postgresql.svg +1 -0
- package/eventcatalog/public/icons/languages/prisma.svg +1 -0
- package/eventcatalog/public/icons/languages/purescript.svg +1 -0
- package/eventcatalog/public/icons/languages/python.svg +1 -0
- package/eventcatalog/public/icons/languages/r.svg +1 -0
- package/eventcatalog/public/icons/languages/react.svg +1 -0
- package/eventcatalog/public/icons/languages/reasonml.svg +1 -0
- package/eventcatalog/public/icons/languages/redis.svg +1 -0
- package/eventcatalog/public/icons/languages/ruby.svg +1 -0
- package/eventcatalog/public/icons/languages/rust.svg +1 -0
- package/eventcatalog/public/icons/languages/sass.svg +1 -0
- package/eventcatalog/public/icons/languages/scala.svg +1 -0
- package/eventcatalog/public/icons/languages/solidity.svg +1 -0
- package/eventcatalog/public/icons/languages/spring.svg +1 -0
- package/eventcatalog/public/icons/languages/sqlite.svg +1 -0
- package/eventcatalog/public/icons/languages/svelte.svg +1 -0
- package/eventcatalog/public/icons/languages/swagger.svg +1 -0
- package/eventcatalog/public/icons/languages/swift.svg +1 -0
- package/eventcatalog/public/icons/languages/tailwind.svg +1 -0
- package/eventcatalog/public/icons/languages/terraform.svg +1 -0
- package/eventcatalog/public/icons/languages/toml.svg +1 -0
- package/eventcatalog/public/icons/languages/typescript.svg +1 -0
- package/eventcatalog/public/icons/languages/unity.svg +1 -0
- package/eventcatalog/public/icons/languages/vim.svg +1 -0
- package/eventcatalog/public/icons/languages/vue.svg +1 -0
- package/eventcatalog/public/icons/languages/webassembly.svg +1 -0
- package/eventcatalog/public/icons/languages/yaml.svg +1 -0
- package/eventcatalog/public/icons/languages/zig.svg +1 -0
- package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.astro +12 -0
- package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.tsx +176 -0
- package/eventcatalog/src/components/MDX/CodeGroup/MarkdownCodeGroup.tsx +22 -0
- package/eventcatalog/src/components/MDX/CodeGroup/code-group-icons.ts +345 -0
- package/eventcatalog/src/components/MDX/CodeGroup/code-group.css +22 -0
- package/eventcatalog/src/components/MDX/CodeGroup/parse-panels.ts +11 -0
- package/eventcatalog/src/components/MDX/Columns/Column.astro +10 -0
- package/eventcatalog/src/components/MDX/Columns/Columns.astro +14 -0
- package/eventcatalog/src/components/MDX/Columns/MarkdownColumns.tsx +37 -0
- package/eventcatalog/src/components/MDX/Columns/layout.ts +16 -0
- package/eventcatalog/src/components/MDX/components.tsx +6 -0
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +1 -1
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +151 -114
- package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +510 -248
- package/eventcatalog/src/components/SchemaExplorer/SchemaFlows.tsx +76 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaGraph.tsx +47 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +11 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaUsage.tsx +17 -0
- package/eventcatalog/src/components/SchemaExplorer/types.ts +48 -3
- package/eventcatalog/src/components/SchemaExplorer/utils.ts +28 -1
- package/eventcatalog/src/content.config.ts +28 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +38 -7
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +144 -37
- package/eventcatalog/src/pages/schemas/explorer/index.astro +5 -0
- package/eventcatalog/src/plugins/empty-collection-warning.d.ts +21 -0
- package/eventcatalog/src/plugins/empty-collection-warning.mjs +107 -0
- package/eventcatalog/src/plugins/quiet-empty-collections-logger.mjs +11 -0
- package/eventcatalog/src/remark-plugins/code-group.ts +39 -0
- package/eventcatalog/src/remark-plugins/markdown-code-group.ts +59 -0
- package/eventcatalog/src/remark-plugins/markdown-columns.ts +66 -0
- package/eventcatalog/src/utils/collections/channels.ts +12 -4
- package/eventcatalog/src/utils/collections/examples.ts +133 -41
- package/eventcatalog/src/utils/collections/flows.ts +43 -0
- package/eventcatalog/src/utils/collections/messages.ts +2 -2
- package/eventcatalog/src/utils/collections/schemas.ts +15 -0
- package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +17 -15
- package/eventcatalog/src/utils/schema-explorer.ts +73 -7
- package/eventcatalog/src/utils/schema-usage-graph.ts +92 -0
- package/package.json +5 -4
- package/dist/chunk-RDYYZQYU.js +0 -18
- package/eventcatalog/src/components/EnvironmentDropdown.test.ts +0 -64
- package/eventcatalog/src/components/Grids/message-link.spec.ts +0 -59
- package/eventcatalog/src/components/MDX/CustomProperties/custom-properties.spec.ts +0 -38
- package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.spec.ts +0 -116
- package/eventcatalog/src/components/SchemaExplorer/JSONSchemaViewer.test.tsx +0 -114
- package/eventcatalog/src/components/SchemaExplorer/ProtobufSchemaViewer.test.tsx +0 -91
- package/eventcatalog/src/components/SchemaExplorer/SchemaViewerHover.test.tsx +0 -33
- package/eventcatalog/src/components/SchemaExplorer/protobuf-validation.test.ts +0 -84
- package/eventcatalog/src/components/Search/search-utils.spec.ts +0 -173
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.spec.ts +0 -105
- package/eventcatalog/src/components/navigation-progress.spec.ts +0 -68
- package/eventcatalog/src/enterprise/directory/user-team-directory.spec.ts +0 -527
- package/eventcatalog/src/enterprise/fields/field-extractor.test.ts +0 -302
- package/eventcatalog/src/enterprise/fields/fields-db.test.ts +0 -185
- package/eventcatalog/src/stores/eventcatalog-store.spec.ts +0 -60
- package/eventcatalog/src/utils/collections/glob-loader.spec.ts +0 -87
- package/dist/{chunk-6K7XZAYI.js → chunk-A2RZR3U4.js} +3 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { ArrowTopRightOnSquareIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
|
|
3
|
+
import SchemaGraph from './SchemaGraph';
|
|
4
|
+
import type { FlowUsage, SchemaItem } from './types';
|
|
5
|
+
import { getSchemaRelationshipHref } from './utils';
|
|
6
|
+
|
|
7
|
+
interface SchemaFlowsProps {
|
|
8
|
+
message: SchemaItem;
|
|
9
|
+
flows: FlowUsage[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const flowKey = (flow: FlowUsage) => `${flow.id}-${flow.version}`;
|
|
13
|
+
|
|
14
|
+
/** The diagram of a flow the message appears in, with a picker when it appears in several. */
|
|
15
|
+
export default function SchemaFlows({ message, flows }: SchemaFlowsProps) {
|
|
16
|
+
const [selectedKey, setSelectedKey] = useState(() => (flows[0] ? flowKey(flows[0]) : ''));
|
|
17
|
+
// Keep the selection valid when the message (and so the list of flows) changes.
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!flows.some((flow) => flowKey(flow) === selectedKey)) setSelectedKey(flows[0] ? flowKey(flows[0]) : '');
|
|
20
|
+
}, [flows, selectedKey]);
|
|
21
|
+
|
|
22
|
+
const selected = flows.find((flow) => flowKey(flow) === selectedKey) ?? flows[0];
|
|
23
|
+
if (!selected) return null;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="flex h-full flex-col overflow-auto pr-1">
|
|
27
|
+
<div className="mb-4 flex shrink-0 flex-wrap items-center gap-3">
|
|
28
|
+
{flows.length > 1 ? (
|
|
29
|
+
<label className="relative inline-flex items-center">
|
|
30
|
+
<span className="sr-only">Flow</span>
|
|
31
|
+
<select
|
|
32
|
+
value={flowKey(selected)}
|
|
33
|
+
onChange={(event) => setSelectedKey(event.target.value)}
|
|
34
|
+
className="appearance-none rounded-md border border-[rgb(var(--ec-input-border))] bg-[rgb(var(--ec-input-bg))] py-1.5 pl-3 pr-8 text-sm font-medium text-[rgb(var(--ec-input-text))] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-accent)/0.4)]"
|
|
35
|
+
>
|
|
36
|
+
{flows.map((flow) => (
|
|
37
|
+
<option key={flowKey(flow)} value={flowKey(flow)}>
|
|
38
|
+
{flow.name || flow.id} (v{flow.version})
|
|
39
|
+
</option>
|
|
40
|
+
))}
|
|
41
|
+
</select>
|
|
42
|
+
<ChevronDownIcon className="pointer-events-none absolute right-2 h-4 w-4 text-[rgb(var(--ec-icon-color))]" />
|
|
43
|
+
</label>
|
|
44
|
+
) : (
|
|
45
|
+
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))]">
|
|
46
|
+
{selected.name || selected.id}
|
|
47
|
+
<span className="ml-2 font-mono text-[11px] font-normal text-[rgb(var(--ec-page-text-muted))]">
|
|
48
|
+
v{selected.version}
|
|
49
|
+
</span>
|
|
50
|
+
</span>
|
|
51
|
+
)}
|
|
52
|
+
<a
|
|
53
|
+
href={getSchemaRelationshipHref({ id: selected.id, version: selected.version, collection: 'flows' })}
|
|
54
|
+
className="inline-flex items-center gap-1 text-xs font-medium text-[rgb(var(--ec-accent))] hover:underline"
|
|
55
|
+
>
|
|
56
|
+
Open flow
|
|
57
|
+
<ArrowTopRightOnSquareIcon className="h-3.5 w-3.5" />
|
|
58
|
+
</a>
|
|
59
|
+
{selected.summary && <span className="basis-full text-xs text-[rgb(var(--ec-page-text-muted))]">{selected.summary}</span>}
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{selected.graph ? (
|
|
63
|
+
<SchemaGraph
|
|
64
|
+
key={flowKey(selected)}
|
|
65
|
+
id={`schema-flow-${message.collection}-${message.data.id}-${message.data.version}-${flowKey(selected)}`}
|
|
66
|
+
graph={selected.graph}
|
|
67
|
+
showLegend={false}
|
|
68
|
+
/>
|
|
69
|
+
) : (
|
|
70
|
+
<p className="rounded-xl border border-dashed border-[rgb(var(--ec-page-border))] px-4 py-6 text-center text-xs text-[rgb(var(--ec-page-text-muted))]">
|
|
71
|
+
The diagram for this flow could not be built.
|
|
72
|
+
</p>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import AstroNodeGraph from '@components/MDX/NodeGraph/AstroNodeGraph';
|
|
3
|
+
import type { MessageUsageGraph } from '@utils/schema-usage-graph';
|
|
4
|
+
|
|
5
|
+
interface SchemaGraphProps {
|
|
6
|
+
/** Unique on the page: it names the portal element the visualiser mounts into. */
|
|
7
|
+
id: string;
|
|
8
|
+
graph: MessageUsageGraph;
|
|
9
|
+
/** CSS height of the graph box. Omit to fill the remaining height of a flex column parent. */
|
|
10
|
+
height?: string;
|
|
11
|
+
showLegend?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A visualiser node graph inside the schema panel. The visualiser is browser-only, so the
|
|
16
|
+
* graph mounts after hydration into the portal element rendered here; the box keeps its
|
|
17
|
+
* height meanwhile so the tab does not jump.
|
|
18
|
+
*/
|
|
19
|
+
export default function SchemaGraph({ id, graph, height, showLegend = true }: SchemaGraphProps) {
|
|
20
|
+
const [mounted, setMounted] = useState(false);
|
|
21
|
+
useEffect(() => setMounted(true), []);
|
|
22
|
+
const portalId = `${id}-portal`;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<div
|
|
27
|
+
id={portalId}
|
|
28
|
+
className={`not-prose relative w-full overflow-hidden rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg))] ${height ? '' : 'min-h-[20em] flex-1'}`}
|
|
29
|
+
style={height ? { height } : undefined}
|
|
30
|
+
/>
|
|
31
|
+
{mounted && (
|
|
32
|
+
<AstroNodeGraph
|
|
33
|
+
id={id}
|
|
34
|
+
nodes={graph.nodes}
|
|
35
|
+
edges={graph.edges}
|
|
36
|
+
mode="simple"
|
|
37
|
+
linkTo="docs"
|
|
38
|
+
showSearch={false}
|
|
39
|
+
includeKey={showLegend}
|
|
40
|
+
zoomOnScroll={false}
|
|
41
|
+
portalId={portalId}
|
|
42
|
+
disableMessageAnimation={true}
|
|
43
|
+
/>
|
|
44
|
+
)}
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import SchemaDetailsPanel from './SchemaDetailsPanel';
|
|
2
3
|
import type { SchemaItem } from './types';
|
|
3
4
|
|
|
@@ -7,6 +8,11 @@ interface SchemaPageViewerProps {
|
|
|
7
8
|
apiAccessEnabled?: boolean;
|
|
8
9
|
showOwners?: boolean;
|
|
9
10
|
showProducersConsumers?: boolean;
|
|
11
|
+
/** Tab requested in the URL, resolved on the server to avoid a flash of the default tab. */
|
|
12
|
+
initialTab?: string;
|
|
13
|
+
/** Examples rendered on the server through the MDX pipeline, passed as the `examples` slot. */
|
|
14
|
+
examples?: ReactNode;
|
|
15
|
+
hasRenderedExamples?: boolean;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
export default function SchemaPageViewer({
|
|
@@ -15,6 +21,9 @@ export default function SchemaPageViewer({
|
|
|
15
21
|
apiAccessEnabled = false,
|
|
16
22
|
showOwners = true,
|
|
17
23
|
showProducersConsumers = true,
|
|
24
|
+
initialTab,
|
|
25
|
+
examples,
|
|
26
|
+
hasRenderedExamples = false,
|
|
18
27
|
}: SchemaPageViewerProps) {
|
|
19
28
|
const handleVersionChange = (version: string) => {
|
|
20
29
|
// Construct new URL
|
|
@@ -32,6 +41,8 @@ export default function SchemaPageViewer({
|
|
|
32
41
|
apiAccessEnabled={apiAccessEnabled}
|
|
33
42
|
showOwners={showOwners}
|
|
34
43
|
showProducersConsumers={showProducersConsumers}
|
|
44
|
+
initialTab={initialTab}
|
|
45
|
+
renderedExamples={hasRenderedExamples ? examples : undefined}
|
|
35
46
|
/>
|
|
36
47
|
);
|
|
37
48
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import SchemaGraph from './SchemaGraph';
|
|
2
|
+
import type { SchemaItem } from './types';
|
|
3
|
+
|
|
4
|
+
/** Producers, consumers and channels of the message, drawn with the same node graph as the docs page. */
|
|
5
|
+
export default function SchemaUsage({ message }: { message: SchemaItem }) {
|
|
6
|
+
return (
|
|
7
|
+
<div className="flex h-full flex-col overflow-auto pr-1">
|
|
8
|
+
{message.graph ? (
|
|
9
|
+
<SchemaGraph id={`schema-usage-${message.collection}-${message.data.id}-${message.data.version}`} graph={message.graph} />
|
|
10
|
+
) : (
|
|
11
|
+
<p className="rounded-xl border border-dashed border-[rgb(var(--ec-page-border))] px-4 py-6 text-center text-xs text-[rgb(var(--ec-page-text-muted))]">
|
|
12
|
+
No producers or consumers declared for this message.
|
|
13
|
+
</p>
|
|
14
|
+
)}
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import type { CollectionMessageTypes } from '@types';
|
|
2
2
|
import type { MessageExample } from '@utils/collections/examples';
|
|
3
|
+
import type { MessageUsageGraph } from '@utils/schema-usage-graph';
|
|
3
4
|
export type { MessageExample };
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
/** A resource related to a message: something that produces or consumes it, or a flow that includes it. */
|
|
7
|
+
export type SchemaRelationshipCollection = 'services' | 'agents' | 'data-products' | 'flows';
|
|
8
|
+
|
|
9
|
+
export interface SchemaRelationship {
|
|
6
10
|
id: string;
|
|
7
11
|
version: string;
|
|
12
|
+
/** Which kind of resource produces or consumes the message. Defaults to a service when unknown. */
|
|
13
|
+
collection?: SchemaRelationshipCollection;
|
|
14
|
+
name?: string;
|
|
15
|
+
summary?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type Producer = SchemaRelationship;
|
|
19
|
+
export type Consumer = SchemaRelationship;
|
|
20
|
+
|
|
21
|
+
export interface FlowUsage extends SchemaRelationship {
|
|
22
|
+
/** The flow's diagram, as rendered by the visualiser. */
|
|
23
|
+
graph?: MessageUsageGraph;
|
|
8
24
|
}
|
|
9
25
|
|
|
10
|
-
|
|
26
|
+
/** A channel the message is published to. */
|
|
27
|
+
export interface MessageChannel {
|
|
11
28
|
id: string;
|
|
12
29
|
version: string;
|
|
30
|
+
name?: string;
|
|
13
31
|
}
|
|
14
32
|
|
|
15
33
|
export interface Owner {
|
|
@@ -19,6 +37,21 @@ export interface Owner {
|
|
|
19
37
|
href: string;
|
|
20
38
|
}
|
|
21
39
|
|
|
40
|
+
/** Where a remote schema was resolved from. Absent for schema files stored in the catalog. */
|
|
41
|
+
export interface SchemaSourceInfo {
|
|
42
|
+
provider: string;
|
|
43
|
+
/** Browsable link to the schema, when the source provides one. */
|
|
44
|
+
url?: string;
|
|
45
|
+
repository?: string;
|
|
46
|
+
path?: string;
|
|
47
|
+
ref?: string;
|
|
48
|
+
commit?: string;
|
|
49
|
+
/** ISO 8601 timestamp of when the schema was first created in the source. */
|
|
50
|
+
createdAt?: string;
|
|
51
|
+
/** ISO 8601 timestamp of when the schema was last updated in the source. */
|
|
52
|
+
updatedAt?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
22
55
|
export interface SchemaItem {
|
|
23
56
|
collection: CollectionMessageTypes | 'services' | 'domains' | 'data-products';
|
|
24
57
|
data: {
|
|
@@ -29,6 +62,10 @@ export interface SchemaItem {
|
|
|
29
62
|
schemaPath?: string;
|
|
30
63
|
producers?: Producer[];
|
|
31
64
|
consumers?: Consumer[];
|
|
65
|
+
/** Flows with a step that sends or receives this message. */
|
|
66
|
+
flows?: FlowUsage[];
|
|
67
|
+
/** Channels the message is published to. */
|
|
68
|
+
channels?: MessageChannel[];
|
|
32
69
|
producerName?: string;
|
|
33
70
|
owners?: Owner[];
|
|
34
71
|
};
|
|
@@ -36,6 +73,11 @@ export interface SchemaItem {
|
|
|
36
73
|
/** Internal URL for loading this version's content without embedding it in the page. */
|
|
37
74
|
contentUrl?: string;
|
|
38
75
|
schemaExtension?: string;
|
|
76
|
+
/** The schema reference used by the message, for example `source://contracts/events/OrderPlaced.schema.json`. */
|
|
77
|
+
schemaRef?: string;
|
|
78
|
+
/** Display name of the schema entry itself, as declared on the message or reported by the source. */
|
|
79
|
+
schemaName?: string;
|
|
80
|
+
source?: SchemaSourceInfo;
|
|
39
81
|
specType?: string;
|
|
40
82
|
specName?: string;
|
|
41
83
|
specFilenameWithoutExtension?: string;
|
|
@@ -45,12 +87,15 @@ export interface SchemaItem {
|
|
|
45
87
|
dataProductVersion?: string;
|
|
46
88
|
// Examples
|
|
47
89
|
examples?: MessageExample[];
|
|
90
|
+
/** Producer → message → consumer graph for the Usage tab, as rendered by the visualiser. */
|
|
91
|
+
graph?: MessageUsageGraph;
|
|
48
92
|
}
|
|
49
93
|
|
|
50
94
|
export interface SchemaDetails {
|
|
51
95
|
schemaContent: string;
|
|
52
96
|
examples: MessageExample[];
|
|
53
|
-
|
|
97
|
+
graph?: MessageUsageGraph;
|
|
98
|
+
data?: Pick<SchemaItem['data'], 'producers' | 'consumers' | 'flows' | 'channels'>;
|
|
54
99
|
}
|
|
55
100
|
|
|
56
101
|
export interface VersionDiff {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { SchemaRelationshipCollection } from './types';
|
|
2
|
+
import { buildUrl } from '@utils/url-builder';
|
|
3
|
+
|
|
1
4
|
// Schema types that should use SVG icons
|
|
2
5
|
export const ICON_SPECS: Record<string, string> = {
|
|
3
6
|
openapi: 'openapi',
|
|
@@ -45,14 +48,38 @@ export function extractServiceName(refId: string): string {
|
|
|
45
48
|
export function getSchemaRelationshipReference(reference: {
|
|
46
49
|
id: string;
|
|
47
50
|
version?: string;
|
|
48
|
-
|
|
51
|
+
collection?: string;
|
|
52
|
+
name?: string;
|
|
53
|
+
summary?: string;
|
|
54
|
+
data?: { id: string; version: string; name?: string; summary?: string };
|
|
49
55
|
}) {
|
|
56
|
+
const collection = (
|
|
57
|
+
reference.collection === 'agents' || reference.collection === 'data-products' || reference.collection === 'flows'
|
|
58
|
+
? reference.collection
|
|
59
|
+
: 'services'
|
|
60
|
+
) as SchemaRelationshipCollection;
|
|
50
61
|
return {
|
|
51
62
|
id: reference.data?.id ?? reference.id,
|
|
52
63
|
version: reference.data?.version ?? reference.version,
|
|
64
|
+
collection,
|
|
65
|
+
name: reference.data?.name ?? reference.name,
|
|
66
|
+
summary: reference.data?.summary ?? reference.summary,
|
|
53
67
|
};
|
|
54
68
|
}
|
|
55
69
|
|
|
70
|
+
export const SCHEMA_RELATIONSHIP_LABELS: Record<SchemaRelationshipCollection, string> = {
|
|
71
|
+
services: 'Service',
|
|
72
|
+
agents: 'Agent',
|
|
73
|
+
'data-products': 'Data Product',
|
|
74
|
+
flows: 'Flow',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const getSchemaRelationshipHref = (reference: {
|
|
78
|
+
id: string;
|
|
79
|
+
version?: string;
|
|
80
|
+
collection: SchemaRelationshipCollection;
|
|
81
|
+
}) => buildUrl(`/docs/${reference.collection}/${reference.id}/${reference.version}`);
|
|
82
|
+
|
|
56
83
|
export const getLanguageForHighlight = (extension?: string): string => {
|
|
57
84
|
if (!extension) return 'json';
|
|
58
85
|
const ext = extension.toLowerCase();
|
|
@@ -1193,6 +1193,10 @@ const schemas = defineCollection({
|
|
|
1193
1193
|
url: z.string().optional(),
|
|
1194
1194
|
ref: z.string().optional(),
|
|
1195
1195
|
branch: z.string().optional(),
|
|
1196
|
+
repository: z.string().optional(),
|
|
1197
|
+
commit: z.string().optional(),
|
|
1198
|
+
createdAt: z.string().optional(),
|
|
1199
|
+
updatedAt: z.string().optional(),
|
|
1196
1200
|
}),
|
|
1197
1201
|
readOnly: z.boolean().optional(),
|
|
1198
1202
|
})
|
|
@@ -1266,10 +1270,34 @@ const sidebars = defineCollection({
|
|
|
1266
1270
|
schema: sidebarSchema,
|
|
1267
1271
|
});
|
|
1268
1272
|
|
|
1273
|
+
/**
|
|
1274
|
+
* Usage examples: Markdown or MDX files inside a message's `examples/` folder. Loaded as a
|
|
1275
|
+
* collection so they render through the MDX pipeline with EventCatalog's custom components.
|
|
1276
|
+
*/
|
|
1277
|
+
const examples = defineCollection({
|
|
1278
|
+
loader: globWithSafeWatcher({
|
|
1279
|
+
pattern: withIgnoredBuildArtifacts([
|
|
1280
|
+
'**/events/*/examples/**/*.(md|mdx)',
|
|
1281
|
+
'**/events/*/versioned/*/examples/**/*.(md|mdx)',
|
|
1282
|
+
'**/commands/*/examples/**/*.(md|mdx)',
|
|
1283
|
+
'**/commands/*/versioned/*/examples/**/*.(md|mdx)',
|
|
1284
|
+
'**/queries/*/examples/**/*.(md|mdx)',
|
|
1285
|
+
'**/queries/*/versioned/*/examples/**/*.(md|mdx)',
|
|
1286
|
+
]),
|
|
1287
|
+
base: projectDirBase,
|
|
1288
|
+
generateId: ({ entry }) => entry,
|
|
1289
|
+
}),
|
|
1290
|
+
schema: z.object({
|
|
1291
|
+
title: z.string().optional(),
|
|
1292
|
+
summary: z.string().optional(),
|
|
1293
|
+
}),
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1269
1296
|
export const collections = {
|
|
1270
1297
|
events,
|
|
1271
1298
|
commands,
|
|
1272
1299
|
queries,
|
|
1300
|
+
examples,
|
|
1273
1301
|
services,
|
|
1274
1302
|
agents,
|
|
1275
1303
|
adrs,
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
import {
|
|
2
|
+
import { marked } from 'marked';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getCollection, render } from 'astro:content';
|
|
5
|
+
import components from '@components/MDX/components';
|
|
6
|
+
import { getExampleEntriesForMessage } from '@utils/collections/examples';
|
|
3
7
|
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
4
8
|
import Footer from '@layouts/Footer.astro';
|
|
5
9
|
import { Page } from './_[...filename].data';
|
|
6
|
-
import { getLanguageForHighlight } from '@components/SchemaExplorer/utils';
|
|
7
10
|
|
|
8
11
|
export const prerender = Page.prerender;
|
|
9
12
|
export const getStaticPaths = Page.getStaticPaths;
|
|
@@ -12,7 +15,13 @@ const props = await Page.getData(Astro);
|
|
|
12
15
|
const { collection, data, example } = props;
|
|
13
16
|
|
|
14
17
|
const pageTitle = `${collection} | ${data.name} | ${example.title}`.replace(/^\w/, (c: string) => c.toUpperCase());
|
|
15
|
-
|
|
18
|
+
// Prefer the MDX pipeline so EventCatalog components work; fall back to plain Markdown.
|
|
19
|
+
const examplesDir = path.join(path.dirname(props.filePath ?? ''), 'examples');
|
|
20
|
+
const exampleEntry = getExampleEntriesForMessage(await getCollection('examples'), props.filePath).find(
|
|
21
|
+
(entry) => path.relative(examplesDir, entry.filePath ?? '').replace(/\\/g, '/') === example.fileName
|
|
22
|
+
);
|
|
23
|
+
const Content = exampleEntry ? (await render(exampleEntry)).Content : undefined;
|
|
24
|
+
const exampleHtml = !Content && example.renderMode === 'markdown' ? await marked.parse(example.content) : '';
|
|
16
25
|
---
|
|
17
26
|
|
|
18
27
|
<VerticalSideBarLayout title={pageTitle} description={`Example: ${example.title} for ${data.name}`}>
|
|
@@ -24,14 +33,36 @@ const lang = getLanguageForHighlight(example.extension);
|
|
|
24
33
|
{example.title}
|
|
25
34
|
</h1>
|
|
26
35
|
<h2 class="text-lg text-[rgb(var(--ec-page-text-muted))] font-medium mb-1">
|
|
27
|
-
Example for {data.name}
|
|
36
|
+
Example for {data.name}
|
|
37
|
+
<span class="text-[rgb(var(--ec-page-text-muted))]">(v{data.version})</span>
|
|
28
38
|
</h2>
|
|
29
39
|
</div>
|
|
30
40
|
|
|
31
41
|
<div class="mt-6">
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
{example.summary && <p class="mb-4 text-[rgb(var(--ec-page-text-muted))]">{example.summary}</p>}
|
|
43
|
+
{
|
|
44
|
+
Content ? (
|
|
45
|
+
<div class="prose prose-md max-w-none">
|
|
46
|
+
<Content components={components(props)} />
|
|
47
|
+
</div>
|
|
48
|
+
) : example.renderMode === 'markdown' ? (
|
|
49
|
+
<div class="prose prose-md max-w-none" set:html={exampleHtml} />
|
|
50
|
+
) : (
|
|
51
|
+
<pre class="overflow-auto rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-code-bg))] p-5 text-sm">
|
|
52
|
+
<code>{example.content}</code>
|
|
53
|
+
</pre>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
{
|
|
57
|
+
example.usage && (
|
|
58
|
+
<section class="mt-6">
|
|
59
|
+
<h2 class="mb-2 text-sm font-semibold uppercase tracking-wider text-[rgb(var(--ec-page-text-muted))]">Usage</h2>
|
|
60
|
+
<pre class="overflow-auto rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-code-bg))] p-5 text-sm">
|
|
61
|
+
<code>{example.usage}</code>
|
|
62
|
+
</pre>
|
|
63
|
+
</section>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
35
66
|
</div>
|
|
36
67
|
|
|
37
68
|
<Footer />
|