Skip to content

Commit

Permalink
fix/ownerReference (#1078)
Browse files Browse the repository at this point in the history
* fix: change ownerReference to union of string and object

It replaces the `reference` from the ownerReference to a union of
string and an object with id and collection. The string refers to
the owner id. The object with id and collection keep compatibility
with `reference` in case someone use like that.

It adds a collection utility to get the owner from the onwerReference.

Fix #1034

* Create wild-items-shout.md

---------

Co-authored-by: David Boyne <[email protected]>
  • Loading branch information
carlosallexandre and boyney123 authored Jan 10, 2025
1 parent 60919ab commit 04ab91d
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/wild-items-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@eventcatalog/core": patch
---

fix(core): fixed issue with teams/owners not showing in the UI
5 changes: 3 additions & 2 deletions eventcatalog/src/components/SideBars/ChannelSideBar.astro
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
---
import { getEntry, type CollectionEntry } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
import PillListFlat from '@components/Lists/PillListFlat';
import ProtocolList from '@components/Lists/ProtocolList';
import OwnersList from '@components/Lists/OwnersList';
import VersionList from '@components/Lists/VersionList.astro';
import { buildUrl } from '@utils/url-builder';
import { ScrollText } from 'lucide-react';
import RepositoryList from '@components/Lists/RepositoryList.astro';
import { getOwner } from '@utils/collections/owners';
interface Props {
channel: CollectionEntry<'channels'>;
Expand All @@ -15,7 +16,7 @@ interface Props {
const { channel } = Astro.props;
const ownersRaw = channel.data?.owners || [];
const owners = await Promise.all(ownersRaw.map((o) => getEntry(o)));
const owners = await Promise.all<ReturnType<typeof getOwner>>(ownersRaw.map(getOwner));
const filteredOwners = owners.filter((o) => o !== undefined);
const channelParameters: Record<string, { enum?: string[]; description?: string }> = channel.data.parameters || {};
Expand Down
6 changes: 4 additions & 2 deletions eventcatalog/src/components/SideBars/DomainSideBar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import PillListFlat from '@components/Lists/PillListFlat';
import RepositoryList from '@components/Lists/RepositoryList.astro';
import VersionList from '@components/Lists/VersionList.astro';
import { getUbiquitousLanguage } from '@utils/collections/domains';
import { getOwner } from '@utils/collections/owners';
import { buildUrl } from '@utils/url-builder';
import { getEntry, type CollectionEntry } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
import { ScrollText, Workflow } from 'lucide-react';
interface Props {
domain: CollectionEntry<'domains'>;
}
Expand All @@ -20,7 +22,7 @@ const hasUbiquitousLanguage = ubiquitousLanguage.length > 0;
const ubiquitousLanguageDictionary = hasUbiquitousLanguage ? ubiquitousLanguage[0].data.dictionary : [];
const ownersRaw = domain.data?.owners || [];
const owners = await Promise.all(ownersRaw.map((o) => getEntry(o)));
const owners = await Promise.all<ReturnType<typeof getOwner>>(ownersRaw.map(getOwner));
const filteredOwners = owners.filter((o) => o !== undefined);
const serviceList = services.map((p) => ({
Expand Down
6 changes: 4 additions & 2 deletions eventcatalog/src/components/SideBars/MessageSideBar.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import { getEntry, type CollectionEntry } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
import PillListFlat from '@components/Lists/PillListFlat';
import OwnersList from '@components/Lists/OwnersList';
import type { CollectionMessageTypes } from '@types';
Expand All @@ -8,6 +8,8 @@ import VersionList from '@components/Lists/VersionList.astro';
import { buildUrl } from '@utils/url-builder';
import { FileDownIcon, ScrollText, Workflow } from 'lucide-react';
import RepositoryList from '@components/Lists/RepositoryList.astro';
import { getOwner } from '@utils/collections/owners';
interface Props {
message: CollectionEntry<CollectionMessageTypes>;
}
Expand All @@ -19,7 +21,7 @@ const consumers = (message.data.consumers as CollectionEntry<'services'>[]) || [
const channels = (message.data.messageChannels as CollectionEntry<'channels'>[]) || [];
const ownersRaw = message.data?.owners || [];
const owners = await Promise.all(ownersRaw.map((o) => getEntry(o)));
const owners = await Promise.all<ReturnType<typeof getOwner>>(ownersRaw.map(getOwner));
const filteredOwners = owners.filter((o) => o !== undefined);
const producerList = producers.map((p) => ({
Expand Down
6 changes: 4 additions & 2 deletions eventcatalog/src/components/SideBars/ServiceSideBar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import RepositoryList from '@components/Lists/RepositoryList.astro';
import SpecificationsList from '@components/Lists/SpecificationsList.astro';
import VersionList from '@components/Lists/VersionList.astro';
import { buildUrl } from '@utils/url-builder';
import { getEntry, type CollectionEntry } from 'astro:content';
import { getOwner } from '@utils/collections/owners';
import type { CollectionEntry } from 'astro:content';
import { ScrollText, Workflow, FileDownIcon, Code, Link } from 'lucide-react';
import { join } from 'node:path';
interface Props {
service: CollectionEntry<'services'>;
}
Expand All @@ -20,7 +22,7 @@ const sends = (service.data.sends as CollectionEntry<'events'>[]) || [];
const receives = (service.data.receives as CollectionEntry<'events'>[]) || [];
const ownersRaw = service.data?.owners || [];
const owners = await Promise.all(ownersRaw.map((o) => getEntry(o)));
const owners = await Promise.all<ReturnType<typeof getOwner>>(ownersRaw.map(getOwner));
const filteredOwners = owners.filter((o) => o !== undefined);
const sendsList = sends.map((p) => ({
Expand Down
16 changes: 15 additions & 1 deletion eventcatalog/src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,21 @@ const changelogs = defineCollection({
});

// Create a union type for owners
const ownerReference = z.union([reference('users'), reference('teams')]);
const ownerReference = z
.union([
// The ID of the user or team
z.string(),
// The full object with the ID and collection (keep compatibility with `reference`)
z.object({
id: z.string(),
collection: z.enum(['users', 'teams']),
}),
])
.transform(
// This transformation is needed to keep compatibility with `reference`.
// The utilities `getTeams` and `getUsers` rely on this transformation.
(lookup) => ({ id: typeof lookup === 'string' ? lookup : lookup.id })
);

const baseSchema = z.object({
id: z.string(),
Expand Down
43 changes: 43 additions & 0 deletions eventcatalog/src/utils/collections/owners.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { getCollection, type CollectionEntry } from 'astro:content';

const getOwners = (function () {
type Owners = CollectionEntry<'users' | 'teams'>;
let cachedOwners: Map<string, Owners> | null = null;
let initializingPromise: Promise<Map<string, Owners>> | null = null;

/**
* Initializes and caches the owners by fetching from the 'users' and 'teams' collections.
*/
async function init() {
const ownersMap = new Map<string, CollectionEntry<'users' | 'teams'>>();

const owners = await Promise.all([
getCollection('users', (entry) => entry.data.hidden !== true),
getCollection('teams', (entry) => entry.data.hidden !== true),
]);

for (const owner of owners.flat()) {
ownersMap.set(owner.data.id, owner);
}

cachedOwners = ownersMap;
initializingPromise = null;

return cachedOwners;
}

return () =>
cachedOwners || // Return cached owners if already initialized
initializingPromise || // Return the promise if initialization is in progress
(initializingPromise = init()); // Initialize if neither cache nor promise exists
})();

export async function getOwner(lookup: { id: string }): Promise<CollectionEntry<'users' | 'teams'> | undefined> {
const lookupId = typeof lookup === 'string' ? lookup : lookup.id;

const owner = (await getOwners()).get(lookupId);

if (!owner) console.warn(`Entry ${lookupId} not found in "teams"/"users" collections.`);

return owner;
}

0 comments on commit 04ab91d

Please sign in to comment.