@eventcatalog/core 4.8.0 → 4.8.2

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.
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(analytics_exports);
36
36
  var import_os = __toESM(require("os"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.8.0";
39
+ var version = "4.8.2";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-EDMVOV4H.js";
4
- import "../chunk-XDKU675D.js";
3
+ } from "../chunk-KSSKB6IR.js";
4
+ import "../chunk-23XZD2VJ.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -140,7 +140,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
140
140
  var import_os = __toESM(require("os"), 1);
141
141
 
142
142
  // package.json
143
- var version = "4.8.0";
143
+ var version = "4.8.2";
144
144
 
145
145
  // src/constants.ts
146
146
  var VERSION = version;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-TRDXMFBW.js";
4
- import "../chunk-EDMVOV4H.js";
3
+ } from "../chunk-6QNERNKA.js";
4
+ import "../chunk-KSSKB6IR.js";
5
5
  import "../chunk-K2XIENVT.js";
6
- import "../chunk-XDKU675D.js";
6
+ import "../chunk-23XZD2VJ.js";
7
7
  import "../chunk-6QENHZZP.js";
8
8
  export {
9
9
  log_build_default as default
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "4.8.0";
2
+ var version = "4.8.2";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-XDKU675D.js";
3
+ } from "./chunk-23XZD2VJ.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-EDMVOV4H.js";
3
+ } from "./chunk-KSSKB6IR.js";
4
4
  import {
5
5
  countResources,
6
6
  serializeCounts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-XDKU675D.js";
3
+ } from "./chunk-23XZD2VJ.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import os from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-OGZMUG75.js";
3
+ } from "./chunk-5CHDOSI2.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "4.8.0";
28
+ var version = "4.8.2";
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-XDKU675D.js";
3
+ } from "./chunk-23XZD2VJ.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -144,7 +144,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
144
144
  var import_picocolors = __toESM(require("picocolors"), 1);
145
145
 
146
146
  // package.json
147
- var version = "4.8.0";
147
+ var version = "4.8.2";
148
148
 
149
149
  // src/constants.ts
150
150
  var VERSION = version;
@@ -4,8 +4,8 @@ import {
4
4
  import "./chunk-CA4U2JP7.js";
5
5
  import {
6
6
  log_build_default
7
- } from "./chunk-TRDXMFBW.js";
8
- import "./chunk-EDMVOV4H.js";
7
+ } from "./chunk-6QNERNKA.js";
8
+ import "./chunk-KSSKB6IR.js";
9
9
  import "./chunk-K2XIENVT.js";
10
10
  import {
11
11
  FederationConflictError,
@@ -31,10 +31,10 @@ import {
31
31
  } from "./chunk-B7HCX5HM.js";
32
32
  import {
33
33
  generate
34
- } from "./chunk-JCJYBRLL.js";
34
+ } from "./chunk-THS3TMA6.js";
35
35
  import {
36
36
  logger
37
- } from "./chunk-OGZMUG75.js";
37
+ } from "./chunk-5CHDOSI2.js";
38
38
  import {
39
39
  resolve_catalog_dependencies_default
40
40
  } from "./chunk-LHR4G2UO.js";
@@ -54,7 +54,7 @@ import {
54
54
  import "./chunk-W5JQON7Z.js";
55
55
  import {
56
56
  VERSION
57
- } from "./chunk-XDKU675D.js";
57
+ } from "./chunk-23XZD2VJ.js";
58
58
  import {
59
59
  linkCoreNodeModules,
60
60
  resolveInstalledCoreNodeModules
package/dist/generate.cjs CHANGED
@@ -108,7 +108,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
108
108
  var import_picocolors = __toESM(require("picocolors"), 1);
109
109
 
110
110
  // package.json
111
- var version = "4.8.0";
111
+ var version = "4.8.2";
112
112
 
113
113
  // src/constants.ts
114
114
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-JCJYBRLL.js";
4
- import "./chunk-OGZMUG75.js";
5
- import "./chunk-XDKU675D.js";
3
+ } from "./chunk-THS3TMA6.js";
4
+ import "./chunk-5CHDOSI2.js";
5
+ import "./chunk-23XZD2VJ.js";
6
6
  import "./chunk-6QENHZZP.js";
7
7
  export {
8
8
  generate
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.8.0";
39
+ var version = "4.8.2";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-OGZMUG75.js";
4
- import "../chunk-XDKU675D.js";
3
+ } from "../chunk-5CHDOSI2.js";
4
+ import "../chunk-23XZD2VJ.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -956,6 +956,7 @@ const ubiquitousLanguages = defineCollection({
956
956
  },
957
957
  }),
958
958
  schema: z.object({
959
+ editUrl: z.string().optional(),
959
960
  dictionary: z
960
961
  .array(
961
962
  z.object({
@@ -964,6 +965,7 @@ const ubiquitousLanguages = defineCollection({
964
965
  summary: z.string().optional(),
965
966
  description: z.string().optional(),
966
967
  icon: z.string().optional(),
968
+ editUrl: z.string().optional(),
967
969
  })
968
970
  )
969
971
  .optional(),
@@ -0,0 +1,150 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { buildUbiquitousLanguageTermPage, Page, resolveUbiquitousLanguageTermEditUrl } from './_index.data';
3
+
4
+ const mocks = vi.hoisted(() => ({
5
+ isSSR: vi.fn(() => false),
6
+ getDomains: vi.fn(),
7
+ getUbiquitousLanguage: vi.fn(),
8
+ }));
9
+
10
+ vi.mock('@utils/feature', () => ({
11
+ isSSR: () => mocks.isSSR(),
12
+ }));
13
+
14
+ vi.mock('@utils/collections/domains', () => ({
15
+ getDomains: mocks.getDomains,
16
+ getUbiquitousLanguage: mocks.getUbiquitousLanguage,
17
+ }));
18
+
19
+ const domain = {
20
+ collection: 'domains',
21
+ filePath: 'domains/Orders/index.mdx',
22
+ data: {
23
+ id: 'Orders',
24
+ name: 'Orders',
25
+ version: '0.0.1',
26
+ },
27
+ } as any;
28
+
29
+ const term = {
30
+ id: 'Order',
31
+ name: 'Order',
32
+ summary: 'A confirmed intent to purchase',
33
+ };
34
+
35
+ const collection = {
36
+ collection: 'ubiquitousLanguages',
37
+ filePath: 'domains/Orders/ubiquitous-language.mdx',
38
+ data: {
39
+ dictionary: [term],
40
+ },
41
+ } as any;
42
+
43
+ const configEditUrl = 'https://github.com/event-catalog/eventcatalog/edit/main';
44
+
45
+ describe('ubiquitous language term page data', () => {
46
+ beforeEach(() => {
47
+ vi.clearAllMocks();
48
+ mocks.isSSR.mockReturnValue(false);
49
+ mocks.getDomains.mockResolvedValue([domain]);
50
+ mocks.getUbiquitousLanguage.mockResolvedValue([collection]);
51
+ });
52
+
53
+ describe('resolveUbiquitousLanguageTermEditUrl', () => {
54
+ it('uses a per-term editUrl when it is set', () => {
55
+ expect(
56
+ resolveUbiquitousLanguageTermEditUrl({
57
+ term: { ...term, editUrl: 'https://github.com/org/glossary/edit/main/Order.md' },
58
+ collection: { ...collection, data: { ...collection.data, editUrl: 'https://example.com/ignored' } },
59
+ configEditUrl,
60
+ })
61
+ ).toBe('https://github.com/org/glossary/edit/main/Order.md');
62
+ });
63
+
64
+ it('uses a collection-level editUrl when the term does not set one', () => {
65
+ expect(
66
+ resolveUbiquitousLanguageTermEditUrl({
67
+ term,
68
+ collection: { ...collection, data: { ...collection.data, editUrl: 'https://github.com/org/catalog/edit/main/ul.mdx' } },
69
+ configEditUrl,
70
+ })
71
+ ).toBe('https://github.com/org/catalog/edit/main/ul.mdx');
72
+ });
73
+
74
+ it('falls back to the site-wide config.editUrl and the dictionary file path', () => {
75
+ expect(resolveUbiquitousLanguageTermEditUrl({ term, collection, configEditUrl })).toBe(
76
+ 'https://github.com/event-catalog/eventcatalog/edit/main/domains/Orders/ubiquitous-language.mdx'
77
+ );
78
+ });
79
+
80
+ it('returns an empty string when no editUrl is available', () => {
81
+ expect(resolveUbiquitousLanguageTermEditUrl({ term, collection })).toBe('');
82
+ });
83
+ });
84
+
85
+ describe('buildUbiquitousLanguageTermPage', () => {
86
+ it('exposes the dictionary file path and collection editUrl for the Edit this page link', () => {
87
+ const page = buildUbiquitousLanguageTermPage({
88
+ domain,
89
+ collection: {
90
+ ...collection,
91
+ data: {
92
+ editUrl: 'https://github.com/org/catalog/edit/main/ul.mdx',
93
+ dictionary: [term],
94
+ },
95
+ },
96
+ term: { ...term, editUrl: 'https://github.com/org/glossary/edit/main/Order.md' },
97
+ });
98
+
99
+ expect(page.params).toEqual({
100
+ type: 'domains',
101
+ id: 'Orders',
102
+ dictionaryId: 'Order',
103
+ });
104
+ expect(page.props.filePath).toBe('domains/Orders/ubiquitous-language.mdx');
105
+ expect(page.props.collectionEditUrl).toBe('https://github.com/org/catalog/edit/main/ul.mdx');
106
+ expect(page.props.ubiquitousLanguage.editUrl).toBe('https://github.com/org/glossary/edit/main/Order.md');
107
+ expect(
108
+ resolveUbiquitousLanguageTermEditUrl({
109
+ term: page.props.ubiquitousLanguage,
110
+ collection: { filePath: page.props.filePath, data: { editUrl: page.props.collectionEditUrl } },
111
+ configEditUrl,
112
+ })
113
+ ).toBe('https://github.com/org/glossary/edit/main/Order.md');
114
+ });
115
+ });
116
+
117
+ describe('Page.getStaticPaths', () => {
118
+ it('includes the dictionary file path used for the config.editUrl fallback href', async () => {
119
+ const paths = await Page.getStaticPaths();
120
+
121
+ expect(paths).toHaveLength(1);
122
+ expect(paths[0].params.dictionaryId).toBe('Order');
123
+ expect(paths[0].props.filePath).toBe('domains/Orders/ubiquitous-language.mdx');
124
+ expect(
125
+ resolveUbiquitousLanguageTermEditUrl({
126
+ term: paths[0].props.ubiquitousLanguage,
127
+ collection: { filePath: paths[0].props.filePath, data: { editUrl: paths[0].props.collectionEditUrl } },
128
+ configEditUrl,
129
+ })
130
+ ).toBe('https://github.com/event-catalog/eventcatalog/edit/main/domains/Orders/ubiquitous-language.mdx');
131
+ });
132
+ });
133
+
134
+ describe('Page.getData', () => {
135
+ it('resolves the Edit this page href when loading a term in SSR', async () => {
136
+ const props = await Page.getData({
137
+ props: {},
138
+ params: { type: 'domains', id: 'Orders', dictionaryId: 'Order' },
139
+ } as any);
140
+
141
+ expect(
142
+ resolveUbiquitousLanguageTermEditUrl({
143
+ term: props.ubiquitousLanguage,
144
+ collection: { filePath: props.filePath, data: { editUrl: props.collectionEditUrl } },
145
+ configEditUrl,
146
+ })
147
+ ).toBe('https://github.com/event-catalog/eventcatalog/edit/main/domains/Orders/ubiquitous-language.mdx');
148
+ });
149
+ });
150
+ });
@@ -1,7 +1,52 @@
1
- import { getUbiquitousLanguage } from '@utils/collections/domains';
2
- import { getDomains } from '@utils/collections/domains';
1
+ import type { CollectionEntry } from 'astro:content';
2
+ import { getDomains, getUbiquitousLanguage } from '@utils/collections/domains';
3
3
  import { isSSR } from '@utils/feature';
4
4
  import { HybridPage } from '@utils/page-loaders/hybrid-page';
5
+ import { resolveEditUrl } from '@utils/url-builder';
6
+
7
+ type Domain = CollectionEntry<'domains'>;
8
+ type UbiquitousLanguage = CollectionEntry<'ubiquitousLanguages'>;
9
+ type DictionaryTerm = NonNullable<UbiquitousLanguage['data']['dictionary']>[number];
10
+
11
+ export const resolveUbiquitousLanguageTermEditUrl = ({
12
+ term,
13
+ collection,
14
+ configEditUrl,
15
+ }: {
16
+ term: Pick<DictionaryTerm, 'editUrl'>;
17
+ collection: Pick<UbiquitousLanguage, 'filePath'> & { data: Pick<UbiquitousLanguage['data'], 'editUrl'> };
18
+ configEditUrl?: string;
19
+ }) =>
20
+ resolveEditUrl({
21
+ resourceEditUrl: term.editUrl || collection.data.editUrl,
22
+ configEditUrl,
23
+ filePath: collection.filePath,
24
+ });
25
+
26
+ export const buildUbiquitousLanguageTermPage = ({
27
+ domain,
28
+ collection,
29
+ term,
30
+ }: {
31
+ domain: Domain;
32
+ collection: UbiquitousLanguage;
33
+ term: DictionaryTerm;
34
+ }) => ({
35
+ params: {
36
+ type: domain.collection,
37
+ id: domain.data.id,
38
+ dictionaryId: term.id,
39
+ },
40
+ props: {
41
+ type: domain.collection,
42
+ domainId: domain.data.id,
43
+ domain: domain.data,
44
+ ...term,
45
+ ubiquitousLanguage: term,
46
+ filePath: collection.filePath,
47
+ collectionEditUrl: collection.data.editUrl,
48
+ },
49
+ });
5
50
 
6
51
  export class Page extends HybridPage {
7
52
  static async getStaticPaths() {
@@ -19,34 +64,21 @@ export class Page extends HybridPage {
19
64
  return accumulator;
20
65
  }
21
66
 
22
- const dictionary = ubiquitousLanguages[0].data.dictionary;
23
-
24
- if (!dictionary) {
25
- return accumulator;
26
- }
27
-
28
67
  return [
29
68
  ...accumulator,
30
- ...dictionary.map((item) => ({
31
- params: {
32
- type: domain.collection,
33
- id: domain.data.id,
34
- dictionaryId: item.id,
35
- },
36
- props: {
37
- type: domain.collection,
38
- domainId: domain.data.id,
39
- domain: domain.data,
40
- ubiquitousLanguage: item,
41
- ...item,
42
- },
43
- })),
69
+ ...ubiquitousLanguages.flatMap((collection) =>
70
+ (collection.data.dictionary ?? []).map((term) => buildUbiquitousLanguageTermPage({ domain, collection, term }))
71
+ ),
44
72
  ];
45
73
  }, Promise.resolve([]));
46
74
 
47
75
  return pages;
48
76
  }
49
77
 
78
+ protected static hasValidProps(props: any): boolean {
79
+ return Boolean(props?.ubiquitousLanguage && props?.domain);
80
+ }
81
+
50
82
  protected static async fetchData(params: any) {
51
83
  const { getDomains } = await import('@utils/collections/domains');
52
84
  const domains = await getDomains({ getAllVersions: false });
@@ -58,20 +90,14 @@ export class Page extends HybridPage {
58
90
  if (ubiquitousLanguages.length === 0) return null;
59
91
 
60
92
  // Find the ubiquitous language that contains our dictionary item
61
- const ubiquitousLanguage = ubiquitousLanguages.find((l) => l.data.dictionary?.some((d) => d.id === params.dictionaryId));
62
- if (!ubiquitousLanguage) return null;
93
+ const collection = ubiquitousLanguages.find((l) => l.data.dictionary?.some((d) => d.id === params.dictionaryId));
94
+ if (!collection) return null;
63
95
 
64
96
  // Find the specific dictionary item
65
- const item = ubiquitousLanguage.data.dictionary?.find((d) => d.id === params.dictionaryId);
66
- if (!item) return null;
67
-
68
- return {
69
- type: domain.collection,
70
- domainId: domain.data.id,
71
- domain: domain.data,
72
- ubiquitousLanguage: item,
73
- ...item,
74
- };
97
+ const term = collection.data.dictionary?.find((d) => d.id === params.dictionaryId);
98
+ if (!term) return null;
99
+
100
+ return buildUbiquitousLanguageTermPage({ domain, collection, term }).props;
75
101
  }
76
102
 
77
103
  protected static createNotFoundResponse(): Response {
@@ -7,8 +7,10 @@ import { buildUrl } from '@utils/url-builder';
7
7
  import { ClientRouter } from 'astro:transitions';
8
8
  import { marked } from 'marked';
9
9
  import * as LucideIcons from 'lucide-react';
10
+ import { SquarePenIcon } from 'lucide-react';
11
+ import config from '@config';
10
12
 
11
- import { Page } from './_index.data';
13
+ import { Page, resolveUbiquitousLanguageTermEditUrl } from './_index.data';
12
14
 
13
15
  export const prerender = Page.prerender;
14
16
  export const getStaticPaths = Page.getStaticPaths;
@@ -17,6 +19,11 @@ const props = await Page.getData(Astro);
17
19
 
18
20
  const { ubiquitousLanguage } = props;
19
21
  const pageTitle = `${props.type} | ${ubiquitousLanguage.name}`.replace(/^\w/, (c) => c.toUpperCase());
22
+ const editUrl = resolveUbiquitousLanguageTermEditUrl({
23
+ term: ubiquitousLanguage,
24
+ collection: { filePath: props.filePath, data: { editUrl: props.collectionEditUrl } },
25
+ configEditUrl: config.editUrl,
26
+ });
20
27
 
21
28
  marked.setOptions({
22
29
  breaks: true,
@@ -104,6 +111,21 @@ const badges = [
104
111
  }
105
112
 
106
113
  <Footer />
114
+ <div class="flex justify-end">
115
+ {
116
+ editUrl && (
117
+ <div class="flex justify-end">
118
+ <a
119
+ href={editUrl}
120
+ class="text-sm text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))] border border-[rgb(var(--ec-page-border))] rounded-md p-2"
121
+ >
122
+ <SquarePenIcon className="w-4 h-4 inline-block mr-1" />
123
+ Edit this page
124
+ </a>
125
+ </div>
126
+ )
127
+ }
128
+ </div>
107
129
  </div>
108
130
  </div>
109
131
  <ClientRouter />
@@ -53,6 +53,20 @@ export const buildEditUrlForResource = (editUrl: string, filePath: string) => {
53
53
  return `${editUrl}/${cleanFilePath}`;
54
54
  };
55
55
 
56
+ export const resolveEditUrl = ({
57
+ resourceEditUrl,
58
+ configEditUrl,
59
+ filePath,
60
+ }: {
61
+ resourceEditUrl?: string;
62
+ configEditUrl?: string;
63
+ filePath?: string;
64
+ }) => {
65
+ if (resourceEditUrl) return resourceEditUrl;
66
+ if (configEditUrl && filePath) return buildEditUrlForResource(configEditUrl, filePath);
67
+ return '';
68
+ };
69
+
56
70
  // Takes a given url and returns the .mdx url
57
71
  export const toMarkdownUrl = (url: string) => {
58
72
  const trailingSlash = typeof __EC_TRAILING_SLASH__ !== 'undefined' ? __EC_TRAILING_SLASH__ : false;
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "4.8.0",
10
+ "version": "4.8.2",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -32,10 +32,10 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@ai-sdk/react": "^3.0.17",
35
- "@astrojs/markdown-remark": "^7.2.2",
36
- "@astrojs/mdx": "^7.0.5",
37
- "@astrojs/node": "^11.1.0",
38
- "@astrojs/react": "^6.0.2",
35
+ "@astrojs/markdown-remark": "^7.2.4",
36
+ "@astrojs/mdx": "^7.0.8",
37
+ "@astrojs/node": "^11.1.4",
38
+ "@astrojs/react": "^6.0.4",
39
39
  "@astrojs/rss": "^4.0.19",
40
40
  "@asyncapi/avro-schema-parser": "3.0.24",
41
41
  "@asyncapi/parser": "^3.6.0",
@@ -61,7 +61,7 @@
61
61
  "@tanstack/react-table": "^8.17.3",
62
62
  "@xyflow/react": "^12.3.6",
63
63
  "ai": "^6.0.17",
64
- "astro": "^7.2.0",
64
+ "astro": "^7.2.8",
65
65
  "astro-expressive-code": "^0.44.0",
66
66
  "astro-seo": "^0.8.4",
67
67
  "auth-astro": "^4.2.0",
@@ -119,8 +119,8 @@
119
119
  "update-notifier": "^7.3.1",
120
120
  "uuid": "^11.1.1",
121
121
  "zod": "^4.3.6",
122
- "@eventcatalog/sdk": "2.28.0",
123
- "@eventcatalog/linter": "1.1.15",
122
+ "@eventcatalog/linter": "1.1.16",
123
+ "@eventcatalog/sdk": "2.28.1",
124
124
  "@eventcatalog/visualiser": "^4.1.3"
125
125
  },
126
126
  "devDependencies": {