Last active
February 14, 2022 21:00
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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