Skip to content

Instantly share code, notes, and snippets.

@codeliner
Last active February 14, 2022 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codeliner/03347d217e97ea0d93bf3da2d205ed6a to your computer and use it in GitHub Desktop.
Save codeliner/03347d217e97ea0d93bf3da2d205ed6a to your computer and use it in GitHub Desktop.
This Gist is used in my video: prooph board & Cody meet Event Catalog - https://youtu.be/0FAgsPNqUV4
import {Context} from "./Context";
import {CodyHook, CodyResponse, CodyResponseType, Node} from "@proophboard/cody-types";
import {
isCodyError,
mkdirIfNotExistsSync,
nodeNameToPascalCase,
parseJsonMetadata,
writeFileSync
} from "@proophboard/cody-utils";
interface EventMetadata {
version: string;
description: string;
schema: object;
}
interface ServiceMetadata {
summary: string;
description: string;
}
export const onEventHook: CodyHook = async (event: Node, ctx: Context): Promise<CodyResponse> => {
const evtName = nodeNameToPascalCase(event);
const metadata = parseJsonMetadata<EventMetadata>(event);
if(isCodyError(metadata)) {
return metadata;
}
const eventDirWithVersions = await createEventDirWithVersionsIfNotExists(event, ctx, metadata.version);
const eventDir = getEventDirRoot(event, ctx);
if(isCodyError(eventDirWithVersions)) {
return eventDirWithVersions;
}
const producer = getProducer(event);
if(isCodyError(producer)) {
return producer;
}
const consumers = getConsumers(event);
let consumerListStr = '';
if(consumers.length) {
consumerListStr = consumers.map(c => ' - '+c.getName()).join("\n");
consumerListStr = "consumers:\n" + consumerListStr;
}
const schemaTag = metadata.schema.hasOwnProperty('type')? '\n<Schema />\n' : '';
const indexMD = `---
name: ${evtName}
version: ${metadata.version}
summary: |
${event.getDescription()}
producers:
- ${producer.getName()}
${consumerListStr}
---
${metadata.description}
<Mermaid />
${schemaTag}
`;
const paths = [eventDirWithVersions];
if(eventDir !== eventDirWithVersions) {
paths.push(eventDir);
}
for (const path of paths) {
const writeIndexMdRes = writeFileSync(path + '/index.md', indexMD);
if(isCodyError(writeIndexMdRes)) {
return writeIndexMdRes;
}
if(metadata.schema.hasOwnProperty('type')) {
const writeSchemaRes = writeFileSync(path + '/schema.json', JSON.stringify(metadata.schema, null, 2));
if(isCodyError(writeSchemaRes)) {
return writeSchemaRes;
}
}
}
const services = [...consumers, producer];
const servicesError = await upsertServices(services, ctx);
if(isCodyError(servicesError)) {
return servicesError;
}
return {
cody: `I've added version ${metadata.version} of event ${evtName} to Event Catalog`
}
}
const getEventDirRoot = (event: Node, ctx: Context): string => {
return ctx.srcFolder + '/events/' + nodeNameToPascalCase(event);
}
const createEventDirWithVersionsIfNotExists = async (event: Node, ctx: Context, version?: string): Promise<CodyResponse | string> => {
const eventDir = getEventDirRoot(event, ctx);
const eventDirRes = mkdirIfNotExistsSync(eventDir);
if(isCodyError(eventDirRes)) {
return eventDirRes;
}
if(version) {
const versionsDir = mkdirIfNotExistsSync(eventDir + '/versioned');
if(isCodyError(versionsDir)) {
return versionsDir;
}
const versionDir = eventDir + '/versioned/' + version;
const versionDirRes = mkdirIfNotExistsSync(versionDir);
if(isCodyError(versionDirRes)) {
return versionDirRes;
}
return versionDir;
}
return eventDir;
}
const getProducer = (event: Node): Node | CodyResponse => {
const parent = event.getParent();
if(!parent) {
return {
cody: `Here is something wrong. Event ${event.getName()} has no parent, but I need this info to determine the producer of the event.`,
type: CodyResponseType.Error
}
}
return parent;
}
const getConsumers = (event: Node): Node[] => {
const consumers: Node[] = [];
event.getTargets().forEach(target => {
const consumer = target.getParent();
if(consumer) {
consumers.push(consumer);
}
})
return consumers;
}
const upsertServices = async (services: Node[], ctx: Context): Promise<CodyResponse | boolean> => {
for (const service of services) {
const serviceDir = ctx.srcFolder + '/services/' + service.getName();
const metadata = parseJsonMetadata<ServiceMetadata>(service);
if(isCodyError(metadata)) {
return metadata;
}
const serviceDirRes = mkdirIfNotExistsSync(serviceDir);
if(isCodyError(serviceDirRes)) {
return serviceDirRes;
}
const indexMd = `---
name: ${service.getName()}
summary: |
${metadata.summary}
---
${metadata.description}
<Mermaid />
`;
const indexMdRes = writeFileSync(serviceDir + '/index.md', indexMd);
if(isCodyError(indexMdRes)) {
return indexMdRes;
}
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment