@eventcatalog/core 3.43.1 → 3.44.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 (48) 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 +50 -2
  4. package/dist/analytics/log-build.js +4 -4
  5. package/dist/catalog-to-astro-content-directory.cjs +31 -1
  6. package/dist/catalog-to-astro-content-directory.js +2 -2
  7. package/dist/{chunk-2GQO7I7E.js → chunk-3UVY6YHH.js} +2 -2
  8. package/dist/{chunk-O6KT4DPL.js → chunk-4SMA4HQ3.js} +1 -1
  9. package/dist/{chunk-5T63CXKU.js → chunk-6QENHZZP.js} +32 -2
  10. package/dist/{chunk-ULZYHF3V.js → chunk-B7HCX5HM.js} +1 -1
  11. package/dist/{chunk-OOX6HAE4.js → chunk-DKKPJ3QM.js} +20 -2
  12. package/dist/{chunk-KV5FCOV4.js → chunk-EPDZMVQ3.js} +1 -1
  13. package/dist/{chunk-Z5QHV4ZY.js → chunk-L26L4Y5J.js} +1 -1
  14. package/dist/{chunk-WAJIJEI3.js → chunk-LHR4G2UO.js} +1 -1
  15. package/dist/{chunk-C6S5P57F.js → chunk-MFLSPCEA.js} +1 -1
  16. package/dist/constants.cjs +1 -1
  17. package/dist/constants.js +1 -1
  18. package/dist/docs/development/guides/owners/users/02-adding-users.md +1 -2
  19. package/dist/eventcatalog-config-file-utils.cjs +31 -1
  20. package/dist/eventcatalog-config-file-utils.js +1 -1
  21. package/dist/eventcatalog.cjs +50 -2
  22. package/dist/eventcatalog.config.d.cts +25 -0
  23. package/dist/eventcatalog.config.d.ts +25 -0
  24. package/dist/eventcatalog.js +9 -9
  25. package/dist/features.cjs +31 -1
  26. package/dist/features.js +2 -2
  27. package/dist/generate.cjs +32 -2
  28. package/dist/generate.js +4 -4
  29. package/dist/resolve-catalog-dependencies.cjs +31 -1
  30. package/dist/resolve-catalog-dependencies.js +2 -2
  31. package/dist/utils/cli-logger.cjs +1 -1
  32. package/dist/utils/cli-logger.js +2 -2
  33. package/eventcatalog/astro.config.mjs +9 -1
  34. package/eventcatalog/public/icons/azure.svg +23 -0
  35. package/eventcatalog/src/components/FieldsExplorer/FieldNodeGraph.tsx +2 -2
  36. package/eventcatalog/src/components/Tables/Table.tsx +4 -0
  37. package/eventcatalog/src/components/Tables/columns/DirectorySourceColumn.tsx +84 -0
  38. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +11 -0
  39. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +11 -0
  40. package/eventcatalog/src/content.config.ts +31 -9
  41. package/eventcatalog/src/enterprise/directory/user-team-directory.spec.ts +527 -0
  42. package/eventcatalog/src/enterprise/directory/user-team-directory.ts +191 -0
  43. package/eventcatalog/src/pages/directory/[type]/index.astro +2 -0
  44. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +35 -5
  45. package/eventcatalog/src/pages/docs/users/[id]/index.astro +35 -0
  46. package/eventcatalog/src/stores/eventcatalog-store.spec.ts +60 -0
  47. package/eventcatalog/src/stores/eventcatalog-store.ts +103 -0
  48. package/package.json +8 -8
package/dist/features.cjs CHANGED
@@ -51,6 +51,36 @@ async function cleanup(projectDirectory) {
51
51
  await (0, import_promises.rm)(filePath);
52
52
  }
53
53
  }
54
+ var findNodeModulesDirectory = (directory) => {
55
+ let currentDirectory = directory;
56
+ while (true) {
57
+ const nodeModulesDirectory = import_node_path.default.join(currentDirectory, "node_modules");
58
+ if ((0, import_node_fs.existsSync)(nodeModulesDirectory)) {
59
+ return nodeModulesDirectory;
60
+ }
61
+ const parentDirectory = import_node_path.default.dirname(currentDirectory);
62
+ if (parentDirectory === currentDirectory) {
63
+ return void 0;
64
+ }
65
+ currentDirectory = parentDirectory;
66
+ }
67
+ };
68
+ var linkNodeModulesIntoTempDirectory = async ({ projectDirectory, tempDir }) => {
69
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
70
+ if (!nodeModulesDirectory) {
71
+ return;
72
+ }
73
+ await (0, import_promises.symlink)(nodeModulesDirectory, import_node_path.default.join(tempDir, "node_modules"), "dir");
74
+ };
75
+ var createTemporaryConfigDirectory = async (projectDirectory) => {
76
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
77
+ if (nodeModulesDirectory) {
78
+ return (0, import_promises.mkdtemp)(import_node_path.default.join(nodeModulesDirectory, ".eventcatalog-config-"));
79
+ }
80
+ const tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
81
+ await linkNodeModulesIntoTempDirectory({ projectDirectory, tempDir });
82
+ return tempDir;
83
+ };
54
84
  var getEventCatalogConfigFile = async (projectDirectory) => {
55
85
  let tempDir;
56
86
  try {
@@ -58,7 +88,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
58
88
  const filePath = import_node_path.default.join(projectDirectory, "package.json");
59
89
  const packageJson = JSON.parse(await (0, import_promises.readFile)(filePath, "utf-8"));
60
90
  if (packageJson?.type !== "module") {
61
- tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
91
+ tempDir = await createTemporaryConfigDirectory(projectDirectory);
62
92
  configFilePath = import_node_path.default.join(tempDir, "eventcatalog.config.mjs");
63
93
  await (0, import_promises.copyFile)(import_node_path.default.join(projectDirectory, "eventcatalog.config.js"), configFilePath);
64
94
  }
package/dist/features.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  isAuthEnabled,
4
4
  isIndexedSearchEnabled,
5
5
  isOutputServer
6
- } from "./chunk-ULZYHF3V.js";
7
- import "./chunk-5T63CXKU.js";
6
+ } from "./chunk-B7HCX5HM.js";
7
+ import "./chunk-6QENHZZP.js";
8
8
  export {
9
9
  getProjectOutDir,
10
10
  isAuthEnabled,
package/dist/generate.cjs CHANGED
@@ -49,6 +49,36 @@ async function cleanup(projectDirectory) {
49
49
  await (0, import_promises.rm)(filePath);
50
50
  }
51
51
  }
52
+ var findNodeModulesDirectory = (directory) => {
53
+ let currentDirectory = directory;
54
+ while (true) {
55
+ const nodeModulesDirectory = import_node_path.default.join(currentDirectory, "node_modules");
56
+ if ((0, import_node_fs.existsSync)(nodeModulesDirectory)) {
57
+ return nodeModulesDirectory;
58
+ }
59
+ const parentDirectory = import_node_path.default.dirname(currentDirectory);
60
+ if (parentDirectory === currentDirectory) {
61
+ return void 0;
62
+ }
63
+ currentDirectory = parentDirectory;
64
+ }
65
+ };
66
+ var linkNodeModulesIntoTempDirectory = async ({ projectDirectory, tempDir }) => {
67
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
68
+ if (!nodeModulesDirectory) {
69
+ return;
70
+ }
71
+ await (0, import_promises.symlink)(nodeModulesDirectory, import_node_path.default.join(tempDir, "node_modules"), "dir");
72
+ };
73
+ var createTemporaryConfigDirectory = async (projectDirectory) => {
74
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
75
+ if (nodeModulesDirectory) {
76
+ return (0, import_promises.mkdtemp)(import_node_path.default.join(nodeModulesDirectory, ".eventcatalog-config-"));
77
+ }
78
+ const tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
79
+ await linkNodeModulesIntoTempDirectory({ projectDirectory, tempDir });
80
+ return tempDir;
81
+ };
52
82
  var getEventCatalogConfigFile = async (projectDirectory) => {
53
83
  let tempDir;
54
84
  try {
@@ -56,7 +86,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
56
86
  const filePath = import_node_path.default.join(projectDirectory, "package.json");
57
87
  const packageJson = JSON.parse(await (0, import_promises.readFile)(filePath, "utf-8"));
58
88
  if (packageJson?.type !== "module") {
59
- tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
89
+ tempDir = await createTemporaryConfigDirectory(projectDirectory);
60
90
  configFilePath = import_node_path.default.join(tempDir, "eventcatalog.config.mjs");
61
91
  await (0, import_promises.copyFile)(import_node_path.default.join(projectDirectory, "eventcatalog.config.js"), configFilePath);
62
92
  }
@@ -78,7 +108,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
78
108
  var import_picocolors = __toESM(require("picocolors"), 1);
79
109
 
80
110
  // package.json
81
- var version = "3.43.1";
111
+ var version = "3.44.1";
82
112
 
83
113
  // src/constants.ts
84
114
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-2GQO7I7E.js";
4
- import "./chunk-Z5QHV4ZY.js";
5
- import "./chunk-KV5FCOV4.js";
6
- import "./chunk-5T63CXKU.js";
3
+ } from "./chunk-3UVY6YHH.js";
4
+ import "./chunk-L26L4Y5J.js";
5
+ import "./chunk-EPDZMVQ3.js";
6
+ import "./chunk-6QENHZZP.js";
7
7
  export {
8
8
  generate
9
9
  };
@@ -48,6 +48,36 @@ async function cleanup(projectDirectory) {
48
48
  await (0, import_promises.rm)(filePath);
49
49
  }
50
50
  }
51
+ var findNodeModulesDirectory = (directory) => {
52
+ let currentDirectory = directory;
53
+ while (true) {
54
+ const nodeModulesDirectory = import_node_path.default.join(currentDirectory, "node_modules");
55
+ if ((0, import_node_fs.existsSync)(nodeModulesDirectory)) {
56
+ return nodeModulesDirectory;
57
+ }
58
+ const parentDirectory = import_node_path.default.dirname(currentDirectory);
59
+ if (parentDirectory === currentDirectory) {
60
+ return void 0;
61
+ }
62
+ currentDirectory = parentDirectory;
63
+ }
64
+ };
65
+ var linkNodeModulesIntoTempDirectory = async ({ projectDirectory, tempDir }) => {
66
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
67
+ if (!nodeModulesDirectory) {
68
+ return;
69
+ }
70
+ await (0, import_promises.symlink)(nodeModulesDirectory, import_node_path.default.join(tempDir, "node_modules"), "dir");
71
+ };
72
+ var createTemporaryConfigDirectory = async (projectDirectory) => {
73
+ const nodeModulesDirectory = findNodeModulesDirectory(projectDirectory);
74
+ if (nodeModulesDirectory) {
75
+ return (0, import_promises.mkdtemp)(import_node_path.default.join(nodeModulesDirectory, ".eventcatalog-config-"));
76
+ }
77
+ const tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
78
+ await linkNodeModulesIntoTempDirectory({ projectDirectory, tempDir });
79
+ return tempDir;
80
+ };
51
81
  var getEventCatalogConfigFile = async (projectDirectory) => {
52
82
  let tempDir;
53
83
  try {
@@ -55,7 +85,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
55
85
  const filePath = import_node_path.default.join(projectDirectory, "package.json");
56
86
  const packageJson = JSON.parse(await (0, import_promises.readFile)(filePath, "utf-8"));
57
87
  if (packageJson?.type !== "module") {
58
- tempDir = await (0, import_promises.mkdtemp)(import_node_path.default.join((0, import_node_os.tmpdir)(), "eventcatalog-config-"));
88
+ tempDir = await createTemporaryConfigDirectory(projectDirectory);
59
89
  configFilePath = import_node_path.default.join(tempDir, "eventcatalog.config.mjs");
60
90
  await (0, import_promises.copyFile)(import_node_path.default.join(projectDirectory, "eventcatalog.config.js"), configFilePath);
61
91
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  resolve_catalog_dependencies_default
3
- } from "./chunk-WAJIJEI3.js";
4
- import "./chunk-5T63CXKU.js";
3
+ } from "./chunk-LHR4G2UO.js";
4
+ import "./chunk-6QENHZZP.js";
5
5
  export {
6
6
  resolve_catalog_dependencies_default as default
7
7
  };
@@ -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 = "3.43.1";
39
+ var version = "3.44.1";
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-Z5QHV4ZY.js";
4
- import "../chunk-KV5FCOV4.js";
3
+ } from "../chunk-L26L4Y5J.js";
4
+ import "../chunk-EPDZMVQ3.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -37,6 +37,9 @@ const expressiveCodeConfig = {
37
37
  },
38
38
  };
39
39
 
40
+ const markdownRemarkPlugins = [remarkDirective, remarkDirectives, remarkComment, mermaid, plantuml];
41
+ const mdxRemarkPlugins = [...markdownRemarkPlugins, remarkResourceRef];
42
+
40
43
  // https://astro.build/config
41
44
  export default defineConfig({
42
45
  base,
@@ -66,6 +69,11 @@ export default defineConfig({
66
69
  // https://docs.astro.build/en/reference/configuration-reference/#trailingslash
67
70
  trailingSlash: config.trailingSlash === true ? 'always' : 'ignore',
68
71
 
72
+ markdown: {
73
+ remarkPlugins: markdownRemarkPlugins,
74
+ gfm: true,
75
+ },
76
+
69
77
  // just turn this off for all users (for now...)
70
78
  devToolbar: { enabled: false },
71
79
  integrations: [
@@ -76,7 +84,7 @@ export default defineConfig({
76
84
  mdx({
77
85
  // https://docs.astro.build/en/guides/integrations-guide/mdx/#optimize
78
86
  optimize: config.mdxOptimize || false,
79
- remarkPlugins: [remarkDirective, remarkDirectives, remarkComment, mermaid, plantuml, remarkResourceRef],
87
+ remarkPlugins: mdxRemarkPlugins,
80
88
  rehypePlugins: [
81
89
  [
82
90
  rehypeExpressiveCode,
@@ -0,0 +1,23 @@
1
+ <svg viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="a" x1="-1032.17" x2="-1059.21" y1="145.31" y2="65.43" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#114a8b"/>
5
+ <stop offset="1" stop-color="#0669bc"/>
6
+ </linearGradient>
7
+ <linearGradient id="b" x1="-1023.73" x2="-1029.98" y1="108.08" y2="105.97" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
8
+ <stop offset="0" stop-opacity=".3"/>
9
+ <stop offset=".07" stop-opacity=".2"/>
10
+ <stop offset=".32" stop-opacity=".1"/>
11
+ <stop offset=".62" stop-opacity=".05"/>
12
+ <stop offset="1" stop-opacity="0"/>
13
+ </linearGradient>
14
+ <linearGradient id="c" x1="-1027.16" x2="-997.48" y1="147.64" y2="68.56" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
15
+ <stop offset="0" stop-color="#3ccbf4"/>
16
+ <stop offset="1" stop-color="#2892df"/>
17
+ </linearGradient>
18
+ </defs>
19
+ <path fill="url(#a)" d="M33.34 6.54h26.04l-27.03 80.1a4.15 4.15 0 0 1-3.94 2.81H8.15a4.14 4.14 0 0 1-3.93-5.47L29.4 9.38a4.15 4.15 0 0 1 3.94-2.83z"/>
20
+ <path fill="#0078d4" d="M71.17 60.26H29.88a1.91 1.91 0 0 0-1.3 3.31l26.53 24.76a4.17 4.17 0 0 0 2.85 1.13h23.38z"/>
21
+ <path fill="url(#b)" d="M33.34 6.54a4.12 4.12 0 0 0-3.95 2.88L4.25 83.92a4.14 4.14 0 0 0 3.91 5.54h20.79a4.44 4.44 0 0 0 3.4-2.9l5.02-14.78 17.91 16.7a4.24 4.24 0 0 0 2.67.97h23.29L71.02 60.26H41.24L59.47 6.55z"/>
22
+ <path fill="url(#c)" d="M66.6 9.36a4.14 4.14 0 0 0-3.93-2.82H33.65a4.15 4.15 0 0 1 3.93 2.82l25.18 74.62a4.15 4.15 0 0 1-3.93 5.48h29.02a4.15 4.15 0 0 0 3.93-5.48z"/>
23
+ </svg>
@@ -15,8 +15,8 @@ import {
15
15
  Event as EventNodeComponent,
16
16
  Command as CommandNodeComponent,
17
17
  Query as QueryNodeComponent,
18
- Service as ServiceNodeComponent,
19
18
  Field as FieldNodeComponent,
19
+ nodeComponents,
20
20
  } from '@eventcatalog/visualiser';
21
21
  import { X, ChevronDown, ChevronRight, Search, AlertTriangle } from 'lucide-react';
22
22
  import { BoltIcon, ChatBubbleLeftIcon, MagnifyingGlassIcon, ServerIcon } from '@heroicons/react/24/solid';
@@ -88,7 +88,7 @@ function wrapWithContextMenu(Component: React.ComponentType<any>) {
88
88
  // and the catalog means these MemoExoticComponents don't match ComponentType<any>
89
89
  // unless we widen once here.
90
90
  const nodeTypes = {
91
- service: wrapWithContextMenu(ServiceNodeComponent as unknown as React.ComponentType<any>),
91
+ service: wrapWithContextMenu(nodeComponents.service as unknown as React.ComponentType<any>),
92
92
  event: wrapWithContextMenu(EventNodeComponent as unknown as React.ComponentType<any>),
93
93
  command: wrapWithContextMenu(CommandNodeComponent as unknown as React.ComponentType<any>),
94
94
  query: wrapWithContextMenu(QueryNodeComponent as unknown as React.ComponentType<any>),
@@ -51,6 +51,10 @@ export type TData<T extends TCollectionTypes> = {
51
51
  name: string;
52
52
  summary: string;
53
53
  version: string;
54
+ source?: {
55
+ provider: string;
56
+ url?: string;
57
+ };
54
58
  latestVersion?: string; // Defined on getter collection utility
55
59
  draft?: boolean | { title?: string; message: string }; // Draft property from base schema
56
60
  badges?: Array<{
@@ -0,0 +1,84 @@
1
+ import { FileText, Github } from 'lucide-react';
2
+ import { buildUrl } from '@utils/url-builder';
3
+ import type { ReactNode } from 'react';
4
+
5
+ type DirectorySource = {
6
+ provider: string;
7
+ id?: string;
8
+ url?: string;
9
+ };
10
+
11
+ const sourceLabels: Record<string, string> = {
12
+ github: 'GitHub',
13
+ 'microsoft-entra': 'Microsoft Entra ID',
14
+ };
15
+
16
+ const getSourceLabel = (source: DirectorySource) => sourceLabels[source.provider] ?? source.provider;
17
+
18
+ const SourceBadge = ({ source, icon }: { source: DirectorySource; icon: ReactNode }) => {
19
+ const label = getSourceLabel(source);
20
+ const title = `Synced from ${label}`;
21
+
22
+ if (source.url) {
23
+ return (
24
+ <a
25
+ href={source.url}
26
+ target="_blank"
27
+ rel="noreferrer"
28
+ className="group/source inline-flex h-7 w-7 items-center justify-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg)/0.35)] transition-colors hover:bg-[rgb(var(--ec-content-hover))]"
29
+ title={title}
30
+ aria-label={title}
31
+ >
32
+ {icon}
33
+ </a>
34
+ );
35
+ }
36
+
37
+ return (
38
+ <span
39
+ className="inline-flex h-7 w-7 items-center justify-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg)/0.35)]"
40
+ title={title}
41
+ aria-label={title}
42
+ >
43
+ {icon}
44
+ </span>
45
+ );
46
+ };
47
+
48
+ export const DirectorySourceCell = ({ source }: { source?: DirectorySource }) => {
49
+ if (source?.provider === 'github') {
50
+ return (
51
+ <SourceBadge
52
+ source={source}
53
+ icon={
54
+ <Github className="h-4 w-4 text-[rgb(var(--ec-icon-color))] transition-colors group-hover/source:text-[rgb(var(--ec-page-text))]" />
55
+ }
56
+ />
57
+ );
58
+ }
59
+
60
+ if (source?.provider === 'microsoft-entra') {
61
+ return <SourceBadge source={source} icon={<img src={buildUrl('/icons/azure.svg', true)} alt="" className="h-4 w-4" />} />;
62
+ }
63
+
64
+ if (source) {
65
+ return (
66
+ <SourceBadge
67
+ source={source}
68
+ icon={
69
+ <FileText className="h-4 w-4 text-[rgb(var(--ec-icon-color))] transition-colors group-hover/source:text-[rgb(var(--ec-page-text))]" />
70
+ }
71
+ />
72
+ );
73
+ }
74
+
75
+ return (
76
+ <span
77
+ className="inline-flex h-7 w-7 items-center justify-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg)/0.35)] text-[rgb(var(--ec-icon-color))]"
78
+ title="Synced to local file"
79
+ aria-label="Synced to local file"
80
+ >
81
+ <FileText className="h-4 w-4" />
82
+ </span>
83
+ );
84
+ };
@@ -7,6 +7,7 @@ import type { CollectionUserTypes } from '@types';
7
7
  import type { TableConfiguration } from '@types';
8
8
  import { getColorAndIconForCollection } from '@utils/collections/icons';
9
9
  import { getCollectionTextColorClass } from '@utils/collection-colors';
10
+ import { DirectorySourceCell } from './DirectorySourceColumn';
10
11
  const columnHelper = createColumnHelper<TData<CollectionUserTypes>>();
11
12
 
12
13
  const CollectionListCell = ({
@@ -81,6 +82,16 @@ export const columns = (tableConfiguration: TableConfiguration) => [
81
82
  filterFn: filterByName,
82
83
  }),
83
84
 
85
+ columnHelper.accessor('data.source', {
86
+ id: 'source',
87
+ header: () => <span>{tableConfiguration.columns?.source?.label || 'Source'}</span>,
88
+ cell: (info) => <DirectorySourceCell source={info.getValue() as { provider: string; url?: string } | undefined} />,
89
+ meta: {
90
+ showFilter: false,
91
+ className: 'w-[96px]',
92
+ },
93
+ }),
94
+
84
95
  columnHelper.accessor(
85
96
  (row) => {
86
97
  const events = row.data.ownedEvents || [];
@@ -7,6 +7,7 @@ import type { CollectionUserTypes } from '@types';
7
7
  import type { TableConfiguration } from '@types';
8
8
  import { getColorAndIconForCollection } from '@utils/collections/icons';
9
9
  import { getCollectionTextColorClass } from '@utils/collection-colors';
10
+ import { DirectorySourceCell } from './DirectorySourceColumn';
10
11
  const columnHelper = createColumnHelper<TData<CollectionUserTypes>>();
11
12
 
12
13
  const CollectionListCell = ({
@@ -84,6 +85,16 @@ export const columns = (tableConfiguration: TableConfiguration) => [
84
85
  filterFn: filterByName,
85
86
  }),
86
87
 
88
+ columnHelper.accessor('data.source', {
89
+ id: 'source',
90
+ header: () => <span>{tableConfiguration.columns?.source?.label || 'Source'}</span>,
91
+ cell: (info) => <DirectorySourceCell source={info.getValue() as { provider: string; url?: string } | undefined} />,
92
+ meta: {
93
+ showFilter: false,
94
+ className: 'w-[96px]',
95
+ },
96
+ }),
97
+
87
98
  columnHelper.accessor('data.role', {
88
99
  id: 'role',
89
100
  header: () => <span>{tableConfiguration.columns?.role?.label || 'Role'}</span>,
@@ -7,6 +7,8 @@ import { badge, ownerReference } from './content.config-shared-collections';
7
7
  import { ADR_STATUS_VALUES } from './utils/collections/adr-constants';
8
8
  import fs from 'fs';
9
9
  import path from 'path';
10
+ import { userTeamDirectoryLoader } from './enterprise/directory/user-team-directory';
11
+ import config from '@config';
10
12
 
11
13
  // Enterprise Collections
12
14
  import { customPagesSchema, resourceDocsSchema, resourceDocCategoriesSchema } from './enterprise/collections';
@@ -102,6 +104,12 @@ const resourcePointer = z.object({
102
104
  type: z.enum(['agent', 'service', 'event', 'command', 'query', 'flow', 'channel', 'domain', 'user', 'team', 'container']),
103
105
  });
104
106
 
107
+ const directoryEntrySource = z.object({
108
+ provider: z.string(),
109
+ id: z.string().optional(),
110
+ url: z.string().optional(),
111
+ });
112
+
105
113
  const changelogs = defineCollection({
106
114
  loader: glob({
107
115
  pattern: withIgnoredBuildArtifacts(['**/changelog.(md|mdx)']),
@@ -876,17 +884,24 @@ const entities = defineCollection({
876
884
  });
877
885
 
878
886
  const users = defineCollection({
879
- loader: glob({
880
- pattern: withIgnoredBuildArtifacts('users/*.(md|mdx)'),
881
- base: projectDirBase,
882
- generateId: ({ data }) => data.id as string,
887
+ loader: userTeamDirectoryLoader({
888
+ collection: 'users',
889
+ sources: config.directory?.sources,
890
+ conflictStrategy: config.directory?.conflictStrategy,
891
+ local: {
892
+ pattern: withIgnoredBuildArtifacts('users/*.(md|mdx)'),
893
+ base: projectDirBase,
894
+ generateId: ({ data }) => data.id as string,
895
+ },
883
896
  }),
884
897
  schema: z.object({
885
898
  id: z.string(),
886
899
  name: z.string(),
887
- avatarUrl: z.string(),
900
+ avatarUrl: z.string().optional(),
888
901
  role: z.string().optional(),
889
902
  hidden: z.boolean().optional(),
903
+ source: directoryEntrySource.optional(),
904
+ readOnly: z.boolean().optional(),
890
905
  email: z.string().optional(),
891
906
  slackDirectMessageUrl: z.string().optional(),
892
907
  msTeamsDirectMessageUrl: z.string().optional(),
@@ -901,10 +916,15 @@ const users = defineCollection({
901
916
  });
902
917
 
903
918
  const teams = defineCollection({
904
- loader: glob({
905
- pattern: withIgnoredBuildArtifacts('teams/*.(md|mdx)'),
906
- base: projectDirBase,
907
- generateId: ({ data }) => data.id as string,
919
+ loader: userTeamDirectoryLoader({
920
+ collection: 'teams',
921
+ sources: config.directory?.sources,
922
+ conflictStrategy: config.directory?.conflictStrategy,
923
+ local: {
924
+ pattern: withIgnoredBuildArtifacts('teams/*.(md|mdx)'),
925
+ base: projectDirBase,
926
+ generateId: ({ data }) => data.id as string,
927
+ },
908
928
  }),
909
929
  schema: z.object({
910
930
  id: z.string(),
@@ -912,6 +932,8 @@ const teams = defineCollection({
912
932
  summary: z.string().optional(),
913
933
  email: z.string().optional(),
914
934
  hidden: z.boolean().optional(),
935
+ source: directoryEntrySource.optional(),
936
+ readOnly: z.boolean().optional(),
915
937
  slackDirectMessageUrl: z.string().optional(),
916
938
  msTeamsDirectMessageUrl: z.string().optional(),
917
939
  members: z.array(reference('users')).optional(),