@eventcatalog/core 3.29.2 → 3.31.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.
Files changed (113) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-36IA4UE4.js → chunk-7IGMIOQF.js} +1 -1
  6. package/dist/{chunk-EGQGCB2B.js → chunk-HVOLSUC2.js} +1 -1
  7. package/dist/{chunk-DB4IQ3GB.js → chunk-LWVHWR77.js} +1 -1
  8. package/dist/{chunk-VEUNSJ6Z.js → chunk-QIJOBQZ7.js} +1 -1
  9. package/dist/{chunk-MEJOYC5Z.js → chunk-UY5QDWK7.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.js +5 -5
  14. package/dist/generate.cjs +1 -1
  15. package/dist/generate.js +3 -3
  16. package/dist/utils/cli-logger.cjs +1 -1
  17. package/dist/utils/cli-logger.js +2 -2
  18. package/eventcatalog/astro.config.mjs +11 -7
  19. package/eventcatalog/public/logo.png +0 -0
  20. package/eventcatalog/src/components/CopyAsMarkdown.tsx +29 -24
  21. package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
  22. package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
  23. package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
  24. package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
  25. package/eventcatalog/src/components/Header.astro +9 -19
  26. package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
  27. package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
  28. package/eventcatalog/src/components/MDX/Design/Design.astro +1 -1
  29. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
  30. package/eventcatalog/src/components/MDX/Tiles/Tile.astro +11 -8
  31. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
  32. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
  33. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
  34. package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
  35. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
  36. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
  37. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
  38. package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
  39. package/eventcatalog/src/components/Search/Search.astro +1 -1
  40. package/eventcatalog/src/components/Seo.astro +1 -1
  41. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +218 -0
  42. package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +265 -0
  43. package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +371 -0
  44. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +183 -0
  45. package/eventcatalog/src/components/Settings/LogoUpload.tsx +137 -0
  46. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +91 -0
  47. package/eventcatalog/src/components/Settings/ReadOnlyBanner.tsx +18 -0
  48. package/eventcatalog/src/components/Settings/Row.tsx +59 -0
  49. package/eventcatalog/src/components/Settings/SettingsShared.tsx +176 -0
  50. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
  51. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +233 -261
  52. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +116 -68
  53. package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +2 -2
  54. package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
  55. package/eventcatalog/src/components/Tables/Table.tsx +21 -18
  56. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
  57. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
  58. package/eventcatalog/src/content.config.ts +1 -1
  59. package/eventcatalog/src/enterprise/auth/error.astro +1 -1
  60. package/eventcatalog/src/enterprise/auth/login.astro +1 -1
  61. package/eventcatalog/src/enterprise/auth/middleware/middleware-auth.ts +11 -7
  62. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +97 -95
  63. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +232 -181
  64. package/eventcatalog/src/enterprise/feature.ts +2 -1
  65. package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
  66. package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
  67. package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
  68. package/eventcatalog/src/layouts/SettingsLayout.astro +116 -0
  69. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +562 -141
  70. package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
  71. package/eventcatalog/src/pages/_index.astro +253 -256
  72. package/eventcatalog/src/pages/api/settings/ai.ts +57 -0
  73. package/eventcatalog/src/pages/api/settings/general.ts +71 -0
  74. package/eventcatalog/src/pages/api/settings/logo.ts +113 -0
  75. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
  76. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
  77. package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
  78. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +130 -30
  79. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +147 -53
  80. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
  81. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
  82. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +22 -19
  83. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +71 -61
  84. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
  85. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +3 -3
  86. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +6 -32
  87. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +5 -1
  88. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
  89. package/eventcatalog/src/pages/docs/users/[id]/index.astro +12 -5
  90. package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
  91. package/eventcatalog/src/pages/settings/assistant.astro +37 -0
  92. package/eventcatalog/src/pages/settings/billing.astro +17 -0
  93. package/eventcatalog/src/pages/settings/general.astro +32 -0
  94. package/eventcatalog/src/pages/settings/index.astro +21 -0
  95. package/eventcatalog/src/pages/settings/llm-access.astro +34 -0
  96. package/eventcatalog/src/pages/settings/mcp.astro +14 -0
  97. package/eventcatalog/src/pages/studio.astro +1 -1
  98. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
  99. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
  100. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
  101. package/eventcatalog/src/styles/theme.css +95 -30
  102. package/eventcatalog/src/styles/themes/forest.css +17 -9
  103. package/eventcatalog/src/styles/themes/ocean.css +10 -2
  104. package/eventcatalog/src/styles/themes/sapphire.css +10 -2
  105. package/eventcatalog/src/styles/themes/sunset.css +25 -17
  106. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
  107. package/eventcatalog/src/utils/eventcatalog-config/config-schema.ts +49 -0
  108. package/eventcatalog/src/utils/eventcatalog-config/config-writer.ts +149 -0
  109. package/eventcatalog/src/utils/url-builder.ts +4 -2
  110. package/package.json +7 -5
  111. package/eventcatalog/public/logo.svg +0 -14
  112. package/eventcatalog/src/enterprise/plans/index.astro +0 -319
  113. package/eventcatalog/src/pages/docs/llm/llms-services.txt.ts +0 -81
@@ -4,17 +4,69 @@ import { filterByName, filterCollectionByName } from '../filters/custom-filters'
4
4
  import { buildUrl } from '@utils/url-builder';
5
5
  import type { TData } from '../Table';
6
6
  import type { CollectionUserTypes } from '@types';
7
- import type { CollectionEntry } from 'astro:content';
8
- import { ServerIcon, BoltIcon, ChatBubbleLeftIcon, MagnifyingGlassIcon } from '@heroicons/react/24/solid';
9
- import { Users } from 'lucide-react';
10
7
  import type { TableConfiguration } from '@types';
8
+ import { getColorAndIconForCollection } from '@utils/collections/icons';
11
9
  const columnHelper = createColumnHelper<TData<CollectionUserTypes>>();
12
10
 
13
- const getMessageIconAndColor = (collection: string) => {
14
- if (collection === 'events') return { Icon: BoltIcon, color: 'orange' };
15
- if (collection === 'commands') return { Icon: ChatBubbleLeftIcon, color: 'blue' };
16
- if (collection === 'queries') return { Icon: MagnifyingGlassIcon, color: 'green' };
17
- return { Icon: ChatBubbleLeftIcon, color: 'gray' };
11
+ const colorClasses: Record<string, string> = {
12
+ orange: 'text-orange-500',
13
+ blue: 'text-blue-500',
14
+ green: 'text-green-500',
15
+ pink: 'text-pink-500',
16
+ yellow: 'text-yellow-500',
17
+ teal: 'text-teal-500',
18
+ purple: 'text-purple-500',
19
+ red: 'text-red-500',
20
+ gray: 'text-gray-500',
21
+ cyan: 'text-cyan-500',
22
+ };
23
+
24
+ const CollectionListCell = ({
25
+ items,
26
+ emptyText,
27
+ }: {
28
+ items: Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined;
29
+ emptyText: string;
30
+ }) => {
31
+ const [isExpanded, setIsExpanded] = useState(false);
32
+
33
+ if (!items || items.length === 0) {
34
+ return <span className="text-xs text-[rgb(var(--ec-icon-color))]">{emptyText}</span>;
35
+ }
36
+
37
+ const visibleItems = isExpanded ? items : items.slice(0, 4);
38
+ const hiddenCount = items.length - 4;
39
+
40
+ return (
41
+ <div className="flex flex-col gap-1">
42
+ {visibleItems.map((item, index) => {
43
+ const { color, Icon } = getColorAndIconForCollection(item.collection);
44
+ const href = buildUrl(`/docs/${item.collection}/${item.data.id}${item.data.version ? `/${item.data.version}` : ''}`);
45
+
46
+ return (
47
+ <a
48
+ key={`${item.data.id}-${index}`}
49
+ href={href}
50
+ className="group inline-flex items-center gap-1.5 text-[0.8rem] text-[rgb(var(--ec-icon-color))] transition-colors hover:text-[rgb(var(--ec-accent))]"
51
+ >
52
+ <Icon className={`h-3.5 w-3.5 flex-shrink-0 ${colorClasses[color] || 'text-[rgb(var(--ec-icon-color))]'}`} />
53
+ <span className="max-w-[140px] truncate" title={item.data.name}>
54
+ {item.data.name}
55
+ </span>
56
+ {item.data.version && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
57
+ </a>
58
+ );
59
+ })}
60
+ {hiddenCount > 0 && (
61
+ <button
62
+ onClick={() => setIsExpanded(!isExpanded)}
63
+ className="text-xs text-[rgb(var(--ec-accent))] hover:underline text-left"
64
+ >
65
+ {isExpanded ? 'Show less' : `+${hiddenCount} more`}
66
+ </button>
67
+ )}
68
+ </div>
69
+ );
18
70
  };
19
71
 
20
72
  export const columns = (tableConfiguration: TableConfiguration) => [
@@ -24,15 +76,11 @@ export const columns = (tableConfiguration: TableConfiguration) => [
24
76
  cell: (info) => {
25
77
  const team = info.row.original;
26
78
  return (
27
- <a href={buildUrl(`/docs/${team.collection}/${team.data.id}`)} className="group inline-flex items-center">
28
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
29
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
30
- <Users className="h-3 w-3 text-white" />
31
- </span>
32
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
33
- {team.data.name}
34
- </span>
35
- </span>
79
+ <a
80
+ href={buildUrl(`/docs/${team.collection}/${team.data.id}`)}
81
+ className="group inline-flex items-center text-sm font-semibold text-[rgb(var(--ec-page-text))] transition-colors hover:text-[rgb(var(--ec-accent))]"
82
+ >
83
+ <span>{team.data.name}</span>
36
84
  </a>
37
85
  );
38
86
  },
@@ -56,57 +104,14 @@ export const columns = (tableConfiguration: TableConfiguration) => [
56
104
  meta: {
57
105
  showFilter: false,
58
106
  },
59
- cell: (info) => {
60
- const messages = info.getValue() as Array<
61
- CollectionEntry<'events'> | CollectionEntry<'commands'> | CollectionEntry<'queries'>
62
- >;
63
- const [isExpanded, setIsExpanded] = useState(false);
64
-
65
- if (messages?.length === 0 || !messages)
66
- return (
67
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
68
- No messages
69
- </span>
70
- );
71
-
72
- const visibleItems = isExpanded ? messages : messages.slice(0, 4);
73
- const hiddenCount = messages.length - 4;
74
-
75
- return (
76
- <div className="flex flex-col gap-1.5">
77
- {visibleItems.map((message, index: number) => {
78
- const { Icon, color } = getMessageIconAndColor(message.collection);
79
- return (
80
- <a
81
- key={`${message.data.id}-${index}`}
82
- href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.version}`)}
83
- className="group inline-flex items-center"
84
- >
85
- <span
86
- className={`inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-${color}-400 dark:hover:border-${color}-500 hover:bg-${color}-50 dark:hover:bg-${color}-500/10 transition-colors`}
87
- >
88
- <span className={`flex items-center justify-center w-6 h-6 bg-${color}-500 rounded-l-md`}>
89
- <Icon className="h-3 w-3 text-white" />
90
- </span>
91
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
92
- {message.data.name}
93
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{message.data.version}</span>
94
- </span>
95
- </span>
96
- </a>
97
- );
98
- })}
99
- {hiddenCount > 0 && (
100
- <button
101
- onClick={() => setIsExpanded(!isExpanded)}
102
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
103
- >
104
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
105
- </button>
106
- )}
107
- </div>
108
- );
109
- },
107
+ cell: (info) => (
108
+ <CollectionListCell
109
+ items={
110
+ info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined
111
+ }
112
+ emptyText="No messages"
113
+ />
114
+ ),
110
115
  }
111
116
  ),
112
117
 
@@ -117,70 +122,13 @@ export const columns = (tableConfiguration: TableConfiguration) => [
117
122
  filterVariant: 'collection',
118
123
  collectionFilterKey: 'ownedServices',
119
124
  },
120
- cell: (info) => {
121
- const services = info.getValue();
122
- const [isExpanded, setIsExpanded] = useState(false);
123
-
124
- if (services?.length === 0 || !services)
125
- return (
126
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
127
- No services
128
- </span>
129
- );
130
-
131
- const visibleItems = isExpanded ? services : services.slice(0, 4);
132
- const hiddenCount = services.length - 4;
133
-
134
- return (
135
- <div className="flex flex-col gap-1.5">
136
- {visibleItems.map((service: CollectionEntry<'services'>, index: number) => (
137
- <a
138
- key={`${service.data.id}-${index}`}
139
- href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.version}`)}
140
- className="group inline-flex items-center"
141
- >
142
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
143
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
144
- <ServerIcon className="h-3 w-3 text-white" />
145
- </span>
146
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
147
- {service.data.name}
148
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{service.data.version}</span>
149
- </span>
150
- </span>
151
- </a>
152
- ))}
153
- {hiddenCount > 0 && (
154
- <button
155
- onClick={() => setIsExpanded(!isExpanded)}
156
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
157
- >
158
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
159
- </button>
160
- )}
161
- </div>
162
- );
163
- },
125
+ cell: (info) => (
126
+ <CollectionListCell
127
+ items={info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined}
128
+ emptyText="No services"
129
+ />
130
+ ),
164
131
  footer: (info) => info.column.id,
165
132
  filterFn: filterCollectionByName('ownedServices'),
166
133
  }),
167
-
168
- columnHelper.accessor('data.name', {
169
- header: () => <span>{tableConfiguration.columns?.actions?.label || 'Actions'}</span>,
170
- cell: (info) => {
171
- const item = info.row.original;
172
- return (
173
- <a
174
- className="inline-flex items-center px-2.5 py-1 text-xs font-medium text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] border border-[rgb(var(--ec-page-border))] rounded-md hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-page-text))] transition-colors whitespace-nowrap"
175
- href={buildUrl(`/docs/${item.collection}/${item.data.id}`)}
176
- >
177
- View team
178
- </a>
179
- );
180
- },
181
- id: 'actions',
182
- meta: {
183
- showFilter: false,
184
- },
185
- }),
186
134
  ];
@@ -4,17 +4,72 @@ import { filterByName, filterCollectionByName } from '../filters/custom-filters'
4
4
  import { buildUrl } from '@utils/url-builder';
5
5
  import type { TData } from '../Table';
6
6
  import type { CollectionUserTypes } from '@types';
7
- import { User, Users } from 'lucide-react';
8
- import type { CollectionEntry } from 'astro:content';
9
- import { ServerIcon, BoltIcon, ChatBubbleLeftIcon, MagnifyingGlassIcon } from '@heroicons/react/24/solid';
10
7
  import type { TableConfiguration } from '@types';
8
+ import { getColorAndIconForCollection } from '@utils/collections/icons';
11
9
  const columnHelper = createColumnHelper<TData<CollectionUserTypes>>();
12
10
 
13
- const getMessageIconAndColor = (collection: string) => {
14
- if (collection === 'events') return { Icon: BoltIcon, color: 'orange' };
15
- if (collection === 'commands') return { Icon: ChatBubbleLeftIcon, color: 'blue' };
16
- if (collection === 'queries') return { Icon: MagnifyingGlassIcon, color: 'green' };
17
- return { Icon: ChatBubbleLeftIcon, color: 'gray' };
11
+ const colorClasses: Record<string, string> = {
12
+ orange: 'text-orange-500',
13
+ blue: 'text-blue-500',
14
+ green: 'text-green-500',
15
+ pink: 'text-pink-500',
16
+ yellow: 'text-yellow-500',
17
+ teal: 'text-teal-500',
18
+ purple: 'text-purple-500',
19
+ red: 'text-red-500',
20
+ gray: 'text-gray-500',
21
+ cyan: 'text-cyan-500',
22
+ };
23
+
24
+ const CollectionListCell = ({
25
+ items,
26
+ emptyText,
27
+ }: {
28
+ items: Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined;
29
+ emptyText: string;
30
+ }) => {
31
+ const [isExpanded, setIsExpanded] = useState(false);
32
+
33
+ if (!items || items.length === 0) {
34
+ return <span className="text-xs text-[rgb(var(--ec-icon-color))]">{emptyText}</span>;
35
+ }
36
+
37
+ const visibleItems = isExpanded ? items : items.slice(0, 4);
38
+ const hiddenCount = items.length - 4;
39
+
40
+ return (
41
+ <div className="flex flex-col gap-1">
42
+ {visibleItems.map((item, index) => {
43
+ const { color, Icon } = getColorAndIconForCollection(item.collection);
44
+ const href =
45
+ item.collection === 'teams'
46
+ ? buildUrl(`/docs/teams/${item.data.id}`)
47
+ : buildUrl(`/docs/${item.collection}/${item.data.id}${item.data.version ? `/${item.data.version}` : ''}`);
48
+
49
+ return (
50
+ <a
51
+ key={`${item.data.id}-${index}`}
52
+ href={href}
53
+ className="group inline-flex items-center gap-1.5 text-[0.8rem] text-[rgb(var(--ec-icon-color))] transition-colors hover:text-[rgb(var(--ec-accent))]"
54
+ >
55
+ <Icon className={`h-3.5 w-3.5 flex-shrink-0 ${colorClasses[color] || 'text-[rgb(var(--ec-icon-color))]'}`} />
56
+ <span className="max-w-[140px] truncate" title={item.data.name}>
57
+ {item.data.name}
58
+ </span>
59
+ {item.data.version && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
60
+ </a>
61
+ );
62
+ })}
63
+ {hiddenCount > 0 && (
64
+ <button
65
+ onClick={() => setIsExpanded(!isExpanded)}
66
+ className="text-xs text-[rgb(var(--ec-accent))] hover:underline text-left"
67
+ >
68
+ {isExpanded ? 'Show less' : `+${hiddenCount} more`}
69
+ </button>
70
+ )}
71
+ </div>
72
+ );
18
73
  };
19
74
 
20
75
  export const columns = (tableConfiguration: TableConfiguration) => [
@@ -24,16 +79,11 @@ export const columns = (tableConfiguration: TableConfiguration) => [
24
79
  cell: (info) => {
25
80
  const user = info.row.original;
26
81
  return (
27
- <a href={buildUrl(`/docs/${user.collection}/${user.data.id}`)} className="group inline-flex items-center">
28
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-[rgb(var(--ec-accent))] hover:bg-[rgb(var(--ec-accent-subtle))] transition-colors">
29
- <span className="flex items-center justify-center w-6 h-6 bg-[rgb(var(--ec-accent))] rounded-l-md">
30
- <User className="h-3 w-3 text-white" />
31
- </span>
32
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
33
- {user.data.name}
34
- {user.data.role && <span className="text-[rgb(var(--ec-icon-color))] ml-1">({user.data.role})</span>}
35
- </span>
36
- </span>
82
+ <a
83
+ href={buildUrl(`/docs/${user.collection}/${user.data.id}`)}
84
+ className="group inline-flex items-center text-sm font-semibold text-[rgb(var(--ec-page-text))] transition-colors hover:text-[rgb(var(--ec-accent))]"
85
+ >
86
+ <span>{user.data.name}</span>
37
87
  </a>
38
88
  );
39
89
  },
@@ -44,6 +94,22 @@ export const columns = (tableConfiguration: TableConfiguration) => [
44
94
  filterFn: filterByName,
45
95
  }),
46
96
 
97
+ columnHelper.accessor('data.role', {
98
+ id: 'role',
99
+ header: () => <span>{tableConfiguration.columns?.role?.label || 'Role'}</span>,
100
+ cell: (info) => {
101
+ const role = info.getValue() as string | undefined;
102
+ return role ? (
103
+ <span className="text-[0.8rem] text-[rgb(var(--ec-icon-color))]">{role}</span>
104
+ ) : (
105
+ <span className="text-xs text-[rgb(var(--ec-icon-color))]">-</span>
106
+ );
107
+ },
108
+ meta: {
109
+ showFilter: false,
110
+ },
111
+ }),
112
+
47
113
  columnHelper.accessor(
48
114
  (row) => {
49
115
  const events = row.data.ownedEvents || [];
@@ -57,57 +123,14 @@ export const columns = (tableConfiguration: TableConfiguration) => [
57
123
  meta: {
58
124
  showFilter: false,
59
125
  },
60
- cell: (info) => {
61
- const messages = info.getValue() as Array<
62
- CollectionEntry<'events'> | CollectionEntry<'commands'> | CollectionEntry<'queries'>
63
- >;
64
- const [isExpanded, setIsExpanded] = useState(false);
65
-
66
- if (messages?.length === 0 || !messages)
67
- return (
68
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
69
- No messages
70
- </span>
71
- );
72
-
73
- const visibleItems = isExpanded ? messages : messages.slice(0, 4);
74
- const hiddenCount = messages.length - 4;
75
-
76
- return (
77
- <div className="flex flex-col gap-1.5">
78
- {visibleItems.map((message, index: number) => {
79
- const { Icon, color } = getMessageIconAndColor(message.collection);
80
- return (
81
- <a
82
- key={`${message.data.id}-${index}`}
83
- href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.version}`)}
84
- className="group inline-flex items-center"
85
- >
86
- <span
87
- className={`inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-${color}-400 dark:hover:border-${color}-500 hover:bg-${color}-50 dark:hover:bg-${color}-500/10 transition-colors`}
88
- >
89
- <span className={`flex items-center justify-center w-6 h-6 bg-${color}-500 rounded-l-md`}>
90
- <Icon className="h-3 w-3 text-white" />
91
- </span>
92
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
93
- {message.data.name}
94
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{message.data.version}</span>
95
- </span>
96
- </span>
97
- </a>
98
- );
99
- })}
100
- {hiddenCount > 0 && (
101
- <button
102
- onClick={() => setIsExpanded(!isExpanded)}
103
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
104
- >
105
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
106
- </button>
107
- )}
108
- </div>
109
- );
110
- },
126
+ cell: (info) => (
127
+ <CollectionListCell
128
+ items={
129
+ info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined
130
+ }
131
+ emptyText="No messages"
132
+ />
133
+ ),
111
134
  }
112
135
  ),
113
136
 
@@ -118,50 +141,12 @@ export const columns = (tableConfiguration: TableConfiguration) => [
118
141
  filterVariant: 'collection',
119
142
  collectionFilterKey: 'ownedServices',
120
143
  },
121
- cell: (info) => {
122
- const services = info.getValue();
123
- const [isExpanded, setIsExpanded] = useState(false);
124
-
125
- if (services?.length === 0 || !services)
126
- return (
127
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
128
- No services
129
- </span>
130
- );
131
-
132
- const visibleItems = isExpanded ? services : services.slice(0, 4);
133
- const hiddenCount = services.length - 4;
134
-
135
- return (
136
- <div className="flex flex-col gap-1.5">
137
- {visibleItems.map((service: CollectionEntry<'services'>, index: number) => (
138
- <a
139
- key={`${service.data.id}-${index}`}
140
- href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.version}`)}
141
- className="group inline-flex items-center"
142
- >
143
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
144
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
145
- <ServerIcon className="h-3 w-3 text-white" />
146
- </span>
147
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
148
- {service.data.name}
149
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{service.data.version}</span>
150
- </span>
151
- </span>
152
- </a>
153
- ))}
154
- {hiddenCount > 0 && (
155
- <button
156
- onClick={() => setIsExpanded(!isExpanded)}
157
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
158
- >
159
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
160
- </button>
161
- )}
162
- </div>
163
- );
164
- },
144
+ cell: (info) => (
145
+ <CollectionListCell
146
+ items={info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined}
147
+ emptyText="No services"
148
+ />
149
+ ),
165
150
  footer: (info) => info.column.id,
166
151
  filterFn: filterCollectionByName('ownedServices'),
167
152
  }),
@@ -174,69 +159,13 @@ export const columns = (tableConfiguration: TableConfiguration) => [
174
159
  collectionFilterKey: 'associatedTeams',
175
160
  filteredItemHasVersion: false,
176
161
  },
177
- cell: (info) => {
178
- const teams = info.getValue();
179
- const [isExpanded, setIsExpanded] = useState(false);
180
-
181
- if (teams?.length === 0 || !teams)
182
- return (
183
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
184
- No teams
185
- </span>
186
- );
187
-
188
- const visibleItems = isExpanded ? teams : teams.slice(0, 4);
189
- const hiddenCount = teams.length - 4;
190
-
191
- return (
192
- <div className="flex flex-col gap-1.5">
193
- {visibleItems.map((team: CollectionEntry<'teams'>, index: number) => (
194
- <a
195
- key={`${team.data.id}-${index}`}
196
- href={buildUrl(`/docs/teams/${team.data.id}`)}
197
- className="group inline-flex items-center"
198
- >
199
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
200
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
201
- <Users className="h-3 w-3 text-white" />
202
- </span>
203
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
204
- {team.data.name}
205
- </span>
206
- </span>
207
- </a>
208
- ))}
209
- {hiddenCount > 0 && (
210
- <button
211
- onClick={() => setIsExpanded(!isExpanded)}
212
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
213
- >
214
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
215
- </button>
216
- )}
217
- </div>
218
- );
219
- },
162
+ cell: (info) => (
163
+ <CollectionListCell
164
+ items={info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined}
165
+ emptyText="No teams"
166
+ />
167
+ ),
220
168
  footer: (info) => info.column.id,
221
169
  filterFn: filterCollectionByName('associatedTeams'),
222
170
  }),
223
-
224
- columnHelper.accessor('data.name', {
225
- header: () => <span>{tableConfiguration.columns?.actions?.label || 'Actions'}</span>,
226
- cell: (info) => {
227
- const item = info.row.original;
228
- return (
229
- <a
230
- className="inline-flex items-center px-2.5 py-1 text-xs font-medium text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] border border-[rgb(var(--ec-page-border))] rounded-md hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-page-text))] transition-colors whitespace-nowrap"
231
- href={buildUrl(`/docs/${item.collection}/${item.data.id}`)}
232
- >
233
- View profile
234
- </a>
235
- );
236
- },
237
- id: 'actions',
238
- meta: {
239
- showFilter: false,
240
- },
241
- }),
242
171
  ];
@@ -32,7 +32,7 @@ export const projectDirBase = (() => {
32
32
 
33
33
  const withIgnoredBuildArtifacts = (patterns: string | string[]) => {
34
34
  if (process.env.IGNORE_BUILD_ARTIFACTS === 'true') {
35
- return [...patterns, '!dist/**'];
35
+ return Array.isArray(patterns) ? [...patterns, '!dist/**'] : [patterns, '!dist/**'];
36
36
  }
37
37
  return patterns;
38
38
  };
@@ -21,7 +21,7 @@ const errorMessage = errorMessages[error] || errorMessages.Default;
21
21
  <head>
22
22
  <meta charset="UTF-8" />
23
23
  <meta name="viewport" content="width=device-width" />
24
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
24
+ <link rel="icon" type="image/png" href="/logo.png" />
25
25
  <meta name="generator" content={Astro.generator} />
26
26
  <title>Authentication Error - EventCatalog</title>
27
27
  </head>
@@ -102,7 +102,7 @@ const providerConfig = {
102
102
  <head>
103
103
  <meta charset="UTF-8" />
104
104
  <meta name="viewport" content="width=device-width" />
105
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
105
+ <link rel="icon" type="image/png" href="/logo.png" />
106
106
  <meta name="generator" content={Astro.generator} />
107
107
  <title>Sign In | {title}</title>
108
108
  <link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -80,6 +80,16 @@ export function findMatchingRule(rules: Record<string, () => boolean>, pathname:
80
80
  return matches.length > 0 ? matches[0].rule : null;
81
81
  }
82
82
 
83
+ export function getPublicRoutes(isLLMSTextEnabled: boolean) {
84
+ const publicRoutes = ['/auth/login', '/auth/signout', '/auth/error', '/api/auth'];
85
+
86
+ if (!isLLMSTextEnabled) {
87
+ return publicRoutes;
88
+ }
89
+
90
+ return [...publicRoutes, '/docs/llm/llms.txt', '/docs/llm/llms-full.txt', '/docs/llm/schemas.txt'];
91
+ }
92
+
83
93
  export const authMiddleware: MiddlewareHandler = async (context, next) => {
84
94
  const { request, redirect, locals } = context;
85
95
  const url = new URL(request.url);
@@ -97,13 +107,7 @@ export const authMiddleware: MiddlewareHandler = async (context, next) => {
97
107
 
98
108
  // Skip system/browser requests
99
109
  const systemRoutes = ['/.well-known/', '/favicon.ico', '/robots.txt', '/sitemap.xml', '/_astro/', '/__astro'];
100
- let publicRoutes = ['/auth/login', '/auth/signout', '/auth/error', '/api/auth'];
101
-
102
- const llmsRoutes = ['/docs/llm/llms.txt', '/docs/llm/llms-services.txt', '/docs/llm/llms-full.txt'];
103
-
104
- if (isLLMSTextEnabled) {
105
- publicRoutes = [...publicRoutes, ...llmsRoutes];
106
- }
110
+ const publicRoutes = getPublicRoutes(isLLMSTextEnabled);
107
111
 
108
112
  if (
109
113
  pathname.startsWith('/_') ||