@eventcatalog/sdk 2.6.4 → 2.6.6

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 (49) hide show
  1. package/dist/channels.js +3 -3
  2. package/dist/channels.js.map +1 -1
  3. package/dist/channels.mjs +3 -3
  4. package/dist/channels.mjs.map +1 -1
  5. package/dist/commands.js +3 -3
  6. package/dist/commands.js.map +1 -1
  7. package/dist/commands.mjs +3 -3
  8. package/dist/commands.mjs.map +1 -1
  9. package/dist/custom-docs.js.map +1 -1
  10. package/dist/custom-docs.mjs.map +1 -1
  11. package/dist/domains.js +3 -3
  12. package/dist/domains.js.map +1 -1
  13. package/dist/domains.mjs +3 -3
  14. package/dist/domains.mjs.map +1 -1
  15. package/dist/eventcatalog.js +224 -149
  16. package/dist/eventcatalog.js.map +1 -1
  17. package/dist/eventcatalog.mjs +223 -148
  18. package/dist/eventcatalog.mjs.map +1 -1
  19. package/dist/events.js +3 -3
  20. package/dist/events.js.map +1 -1
  21. package/dist/events.mjs +3 -3
  22. package/dist/events.mjs.map +1 -1
  23. package/dist/index.d.mts +60 -30
  24. package/dist/index.d.ts +60 -30
  25. package/dist/index.js +224 -149
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +223 -148
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/messages.js +3 -3
  30. package/dist/messages.js.map +1 -1
  31. package/dist/messages.mjs +4 -4
  32. package/dist/messages.mjs.map +1 -1
  33. package/dist/queries.js +3 -3
  34. package/dist/queries.js.map +1 -1
  35. package/dist/queries.mjs +3 -3
  36. package/dist/queries.mjs.map +1 -1
  37. package/dist/services.d.mts +45 -1
  38. package/dist/services.d.ts +45 -1
  39. package/dist/services.js +27 -3
  40. package/dist/services.js.map +1 -1
  41. package/dist/services.mjs +25 -4
  42. package/dist/services.mjs.map +1 -1
  43. package/dist/teams.d.mts +8 -1
  44. package/dist/teams.d.ts +8 -1
  45. package/dist/teams.js +122 -11
  46. package/dist/teams.js.map +1 -1
  47. package/dist/teams.mjs +121 -11
  48. package/dist/teams.mjs.map +1 -1
  49. package/package.json +1 -1
package/dist/events.js CHANGED
@@ -211,10 +211,10 @@ var writeResource = async (catalogDir, resource, options = {
211
211
  });
212
212
  }
213
213
  };
214
- var getResource = async (catalogDir, id, version, options) => {
214
+ var getResource = async (catalogDir, id, version, options, filePath) => {
215
215
  const attachSchema = options?.attachSchema || false;
216
- const file = await findFileById(catalogDir, id, version);
217
- if (!file) return;
216
+ const file = filePath || (id ? await findFileById(catalogDir, id, version) : void 0);
217
+ if (!file || !import_node_fs2.default.existsSync(file)) return;
218
218
  const { data, content } = import_gray_matter2.default.read(file);
219
219
  if (attachSchema && data?.schemaPath) {
220
220
  const resourceDirectory = (0, import_path.dirname)(file);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/internal/utils.ts","../src/internal/resources.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { findFileById } from './internal/utils';\nimport type { Event } from './types';\nimport {\n addFileToResource,\n getResource,\n getResourcePath,\n getResources,\n rmResourceById,\n versionResource,\n writeResource,\n} from './internal/resources';\n\n/**\n * Returns an event from EventCatalog.\n *\n * You can optionally specify a version to get a specific version of the event\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvent } = utils('/path/to/eventcatalog');\n *\n * // Gets the latest version of the event\n * const event = await getEvent('InventoryAdjusted');\n *\n * // Gets a version of the event\n * const event = await getEvent('InventoryAdjusted', '0.0.1');\n *\n * // Get the event with the schema attached\n * const event = await getEvent('InventoryAdjusted', '0.0.1', { attachSchema: true });\n * ```\n */\nexport const getEvent =\n (directory: string) =>\n async (id: string, version?: string, options?: { attachSchema?: boolean }): Promise<Event> =>\n getResource(directory, id, version, { type: 'event', ...options }) as Promise<Event>;\n\n/**\n * Returns all events from EventCatalog.\n *\n * You can optionally specify if you want to get the latest version of the events.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvents } = utils('/path/to/eventcatalog');\n *\n * // Gets all events (and versions) from the catalog\n * const events = await getEvents();\n *\n * // Gets all events (only latest version) from the catalog\n * const events = await getEvents({ latestOnly: true });\n *\n * // Get all events with the schema attached\n * const events = await getEvents({ attachSchema: true });\n * ```\n */\nexport const getEvents =\n (directory: string) =>\n async (options?: { latestOnly?: boolean; attachSchema?: boolean }): Promise<Event[]> =>\n getResources(directory, { type: 'events', ...options }) as Promise<Event[]>;\n\n/**\n * Write an event to EventCatalog.\n *\n * You can optionally overide the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEvent } = utils('/path/to/eventcatalog');\n *\n * // Write an event to the catalog\n * // Event would be written to events/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * });\n *\n * // Write an event to the catalog but override the path\n * // Event would be written to events/Inventory/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { path: \"/Inventory/InventoryAdjusted\"});\n *\n * // Write a event to the catalog and override the existing content (if there is any)\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { override: true });\n *\n * // Write a event to the catalog and version the previous version\n * // only works if the new version is greater than the previous version\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { versionExistingContent: true });\n *\n * ```\n */\nexport const writeEvent =\n (directory: string) =>\n async (\n event: Event,\n options: { path?: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n override: false,\n format: 'mdx',\n }\n ) =>\n writeResource(directory, { ...event }, { ...options, type: 'event' });\n/**\n * Write an event to a service in EventCatalog.\n *\n * You can optionally override the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEventToService } = utils('/path/to/eventcatalog');\n *\n * // Write an event to a given service in the catalog\n * // Event would be written to services/Inventory/events/InventoryAdjusted\n * await writeEventToService({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { id: 'Inventory' });\n * ```\n */\nexport const writeEventToService =\n (directory: string) =>\n async (\n event: Event,\n service: { id: string; version?: string },\n options: { path?: string; format?: 'md' | 'mdx'; override?: boolean } = { path: '', format: 'mdx', override: false }\n ) => {\n const resourcePath = await getResourcePath(directory, service.id, service.version);\n if (!resourcePath) {\n throw new Error('Service not found');\n }\n\n let pathForEvent =\n service.version && service.version !== 'latest'\n ? `${resourcePath.directory}/versioned/${service.version}/events`\n : `${resourcePath.directory}/events`;\n pathForEvent = join(pathForEvent, event.id);\n await writeResource(directory, { ...event }, { ...options, path: pathForEvent, type: 'event' });\n };\n\n/**\n * Delete an event at it's given path.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEvent } = utils('/path/to/eventcatalog');\n *\n * // removes an event at the given path (events dir is appended to the given path)\n * // Removes the event at events/InventoryAdjusted\n * await rmEvent('/InventoryAdjusted');\n * ```\n */\nexport const rmEvent = (directory: string) => async (path: string) => {\n await fs.rm(join(directory, path), { recursive: true });\n};\n\n/**\n * Delete an event by it's id.\n *\n * Optionally specify a version to delete a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEventById } = utils('/path/to/eventcatalog');\n *\n * // deletes the latest InventoryAdjusted event\n * await rmEventById('InventoryAdjusted');\n *\n * // deletes a specific version of the InventoryAdjusted event\n * await rmEventById('InventoryAdjusted', '0.0.1');\n * ```\n */\nexport const rmEventById = (directory: string) => async (id: string, version?: string, persistFiles?: boolean) => {\n await rmResourceById(directory, id, version, { type: 'event', persistFiles });\n};\n\n/**\n * Version an event by it's id.\n *\n * Takes the latest event and moves it to a versioned directory.\n * All files with this event are also versioned (e.g /events/InventoryAdjusted/schema.json)\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { versionEvent } = utils('/path/to/eventcatalog');\n *\n * // moves the latest InventoryAdjusted event to a versioned directory\n * // the version within that event is used as the version number.\n * await versionEvent('InventoryAdjusted');\n *\n * ```\n */\nexport const versionEvent = (directory: string) => async (id: string) => versionResource(directory, id);\n\n/**\n * Add a file to an event by it's id.\n *\n * Optionally specify a version to add a file to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' }, '0.0.1');\n *\n * ```\n */\nexport const addFileToEvent =\n (directory: string) => async (id: string, file: { content: string; fileName: string }, version?: string) =>\n addFileToResource(directory, id, file, version);\n\n/**\n * Add a schema to an event by it's id.\n *\n * Optionally specify a version to add a schema to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // JSON schema example\n * const schema = {\n * \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n * \"type\": \"object\",\n * \"properties\": {\n * \"name\": {\n * \"type\": \"string\"\n * },\n * \"age\": {\n * \"type\": \"number\"\n * }\n * },\n * \"required\": [\"name\", \"age\"]\n * };\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' }, '0.0.1');\n *\n * ```\n */\nexport const addSchemaToEvent =\n (directory: string) => async (id: string, schema: { schema: string; fileName: string }, version?: string) => {\n await addFileToEvent(directory)(id, { content: schema.schema, fileName: schema.fileName }, version);\n };\n\n/**\n * Check to see if the catalog has a version for the given event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { eventHasVersion } = utils('/path/to/eventcatalog');\n *\n * // returns true if version is found for the given event and version (supports semver)\n * await eventHasVersion('InventoryAdjusted', '0.0.1');\n * await eventHasVersion('InventoryAdjusted', 'latest');\n * await eventHasVersion('InventoryAdjusted', '0.0.x');*\n *\n * ```\n */\nexport const eventHasVersion = (directory: string) => async (id: string, version?: string) => {\n const file = await findFileById(directory, id, version);\n return !!file;\n};\n","import { globSync } from 'glob';\nimport fsSync from 'node:fs';\nimport { copy, CopyFilterAsync, CopyFilterSync } from 'fs-extra';\nimport { join, dirname, normalize, sep as pathSeparator, resolve, basename, relative } from 'node:path';\nimport matter from 'gray-matter';\nimport { satisfies, validRange, valid } from 'semver';\n\n/**\n * Returns true if a given version of a resource id exists in the catalog\n */\nexport const versionExists = async (catalogDir: string, id: string, version: string) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = (await searchFilesForId(files, id, version)) || [];\n return matchedFiles.length > 0;\n};\n\nexport const findFileById = async (catalogDir: string, id: string, version?: string): Promise<string | undefined> => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = (await searchFilesForId(files, id)) || [];\n const latestVersion = matchedFiles.find((path) => !path.includes('versioned'));\n\n // If no version is provided, return the latest version\n if (!version) {\n return latestVersion;\n }\n\n // map files into gray matter to get versions\n const parsedFiles = matchedFiles.map((path) => {\n const { data } = matter.read(path);\n return { ...data, path };\n }) as any[];\n\n const semverRange = validRange(version);\n\n if (semverRange && valid(version)) {\n const match = parsedFiles.filter((c) => satisfies(c.version, semverRange));\n return match.length > 0 ? match[0].path : undefined;\n }\n\n // Order by version\n const sorted = parsedFiles.sort((a, b) => {\n return a.version.localeCompare(b.version);\n });\n\n // latest version\n const match = sorted.length > 0 ? [sorted[sorted.length - 1]] : [];\n\n if (match.length > 0) {\n return match[0].path;\n }\n};\n\nexport const getFiles = async (pattern: string, ignore: string | string[] = '') => {\n try {\n // 1. Normalize the input pattern to handle mixed separators potentially\n const normalizedInputPattern = normalize(pattern);\n\n // 2. Determine the absolute base directory (cwd for glob)\n // Resolve ensures it's absolute. Handles cases with/without globstar.\n const absoluteBaseDir = resolve(\n normalizedInputPattern.includes('**') ? normalizedInputPattern.split('**')[0] : dirname(normalizedInputPattern)\n );\n\n // 3. Determine the pattern part relative to the absolute base directory\n // We extract the part of the normalized pattern that comes *after* the absoluteBaseDir\n let relativePattern = relative(absoluteBaseDir, normalizedInputPattern);\n\n // On Windows, relative() might return empty string if paths are identical,\n // or might need normalization if the original pattern didn't have `**`\n // Example: pattern = 'dir/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\file.md'\n // relative() -> 'file.md'\n // Example: pattern = 'dir/**/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\**\\file.md'\n // relative() -> '**\\file.md'\n // Convert separators in the relative pattern to forward slashes for glob\n relativePattern = relativePattern.replace(/\\\\/g, '/');\n\n const ignoreList = Array.isArray(ignore) ? ignore : [ignore];\n\n const files = globSync(relativePattern, {\n cwd: absoluteBaseDir,\n ignore: ['node_modules/**', ...ignoreList],\n absolute: true,\n nodir: true,\n });\n\n // 5. Normalize results for consistency before returning\n return files.map(normalize);\n } catch (error: any) {\n // Add more diagnostic info to the error\n const absoluteBaseDirForError = resolve(\n normalize(pattern).includes('**') ? normalize(pattern).split('**')[0] : dirname(normalize(pattern))\n );\n const relativePatternForError = relative(absoluteBaseDirForError, normalize(pattern)).replace(/\\\\/g, '/');\n throw new Error(\n `Error finding files for pattern \"${pattern}\" (using cwd: \"${absoluteBaseDirForError}\", globPattern: \"${relativePatternForError}\"): ${error.message}`\n );\n }\n};\n\nexport const readMdxFile = async (path: string) => {\n const { data } = matter.read(path);\n const { markdown, ...frontmatter } = data;\n return { ...frontmatter, markdown };\n};\n\nexport const searchFilesForId = async (files: string[], id: string, version?: string) => {\n // Escape the id to avoid regex issues\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const idRegex = new RegExp(`^id:\\\\s*(['\"]|>-)?\\\\s*${escapedId}['\"]?\\\\s*$`, 'm');\n\n const versionRegex = new RegExp(`^version:\\\\s*['\"]?${version}['\"]?\\\\s*$`, 'm');\n\n const matches = files.map((file) => {\n const content = fsSync.readFileSync(file, 'utf-8');\n const hasIdMatch = content.match(idRegex);\n\n // Check version if provided\n if (version && !content.match(versionRegex)) {\n return undefined;\n }\n\n if (hasIdMatch) {\n return file;\n }\n });\n\n return matches.filter(Boolean).filter((file) => file !== undefined);\n};\n\n/**\n * Function to copy a directory from source to target, uses a tmp directory\n * @param catalogDir\n * @param source\n * @param target\n * @param filter\n */\nexport const copyDir = async (catalogDir: string, source: string, target: string, filter?: CopyFilterAsync | CopyFilterSync) => {\n const tmpDirectory = join(catalogDir, 'tmp');\n fsSync.mkdirSync(tmpDirectory, { recursive: true });\n\n // Copy everything over\n await copy(source, tmpDirectory, {\n overwrite: true,\n filter,\n });\n\n await copy(tmpDirectory, target, {\n overwrite: true,\n filter,\n });\n\n // Remove the tmp directory\n fsSync.rmSync(tmpDirectory, { recursive: true });\n};\n\n// Makes sure values in sends/recieves are unique\nexport const uniqueVersions = (messages: { id: string; version: string }[]): { id: string; version: string }[] => {\n const uniqueSet = new Set();\n\n return messages.filter((message) => {\n const key = `${message.id}-${message.version}`;\n if (!uniqueSet.has(key)) {\n uniqueSet.add(key);\n return true;\n }\n return false;\n });\n};\n","import { dirname, join } from 'path';\nimport { copyDir, findFileById, getFiles, searchFilesForId, versionExists } from './utils';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport fsSync from 'node:fs';\nimport { Message, Service, CustomDoc } from '../types';\nimport { satisfies } from 'semver';\nimport { lock, unlock } from 'proper-lockfile';\n\ntype Resource = Service | Message | CustomDoc;\n\nexport const versionResource = async (catalogDir: string, id: string) => {\n // Find all the events in the directory\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = await searchFilesForId(files, id);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No resource found with id: ${id}`);\n }\n\n // Event that is in the route of the project\n const file = matchedFiles[0];\n const sourceDirectory = dirname(file);\n const { data: { version = '0.0.1' } = {} } = matter.read(file);\n const targetDirectory = getVersionedDirectory(sourceDirectory, version);\n\n fsSync.mkdirSync(targetDirectory, { recursive: true });\n\n // Copy the event to the versioned directory\n await copyDir(catalogDir, sourceDirectory, targetDirectory, (src) => {\n return !src.includes('versioned');\n });\n\n // Remove all the files in the root of the resource as they have now been versioned\n await fs.readdir(sourceDirectory).then(async (resourceFiles) => {\n await Promise.all(\n resourceFiles.map(async (file) => {\n if (file !== 'versioned') {\n fsSync.rmSync(join(sourceDirectory, file), { recursive: true });\n }\n })\n );\n });\n};\n\nexport const writeResource = async (\n catalogDir: string,\n resource: Resource,\n options: { path?: string; type: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n type: '',\n override: false,\n versionExistingContent: false,\n format: 'mdx',\n }\n) => {\n const path = options.path || `/${resource.id}`;\n const fullPath = join(catalogDir, path);\n const format = options.format || 'mdx';\n\n // Create directory if it doesn't exist\n fsSync.mkdirSync(fullPath, { recursive: true });\n\n // Create or get lock file path\n const lockPath = join(fullPath, `index.${format}`);\n\n // Ensure the file exists before attempting to lock it\n if (!fsSync.existsSync(lockPath)) {\n fsSync.writeFileSync(lockPath, '');\n }\n\n try {\n // Acquire lock with retry\n await lock(lockPath, {\n retries: 5,\n stale: 10000, // 10 seconds\n });\n\n const exists = await versionExists(catalogDir, resource.id, resource.version);\n\n if (exists && !options.override) {\n throw new Error(`Failed to write ${resource.id} (${options.type}) as the version ${resource.version} already exists`);\n }\n\n const { markdown, ...frontmatter } = resource;\n\n if (options.versionExistingContent && !exists) {\n const currentResource = await getResource(catalogDir, resource.id);\n\n if (currentResource) {\n if (satisfies(resource.version, `>${currentResource.version}`)) {\n await versionResource(catalogDir, resource.id);\n } else {\n throw new Error(`New version ${resource.version} is not greater than current version ${currentResource.version}`);\n }\n }\n }\n\n const document = matter.stringify(markdown.trim(), frontmatter);\n fsSync.writeFileSync(lockPath, document);\n } finally {\n // Always release the lock\n await unlock(lockPath).catch(() => {});\n }\n};\n\nexport const getResource = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; attachSchema?: boolean }\n): Promise<Resource | undefined> => {\n const attachSchema = options?.attachSchema || false;\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n const { data, content } = matter.read(file);\n\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResourcePath = async (catalogDir: string, id: string, version?: string) => {\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n return {\n fullPath: file,\n relativePath: file.replace(catalogDir, ''),\n directory: dirname(file.replace(catalogDir, '')),\n };\n};\n\nexport const getResources = async (\n catalogDir: string,\n {\n type,\n latestOnly = false,\n ignore = [],\n pattern = '',\n attachSchema = false,\n }: { type: string; pattern?: string; latestOnly?: boolean; ignore?: string[]; attachSchema?: boolean }\n): Promise<Resource[] | undefined> => {\n const ignoreList = latestOnly ? `**/versioned/**` : '';\n const filePattern = pattern || `${catalogDir}/**/${type}/**/index.{md,mdx}`;\n const files = await getFiles(filePattern, [ignoreList, ...ignore]);\n\n if (files.length === 0) return;\n\n return files.map((file) => {\n const { data, content } = matter.read(file);\n\n // Attach the schema if the attachSchema option is set to true\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n });\n};\n\nexport const rmResourceById = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; persistFiles?: boolean }\n) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = await searchFilesForId(files, id, version);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No ${options?.type || 'resource'} found with id: ${id}`);\n }\n\n if (options?.persistFiles) {\n await Promise.all(\n matchedFiles.map(async (file) => {\n await fs.rm(file, { recursive: true });\n })\n );\n } else {\n await Promise.all(\n matchedFiles.map(async (file) => {\n const directory = dirname(file);\n await fs.rm(directory, { recursive: true, force: true });\n })\n );\n }\n};\n\nexport const addFileToResource = async (\n catalogDir: string,\n id: string,\n file: { content: string; fileName: string },\n version?: string\n) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory to write file to');\n\n let fileContent = file.content.trim();\n\n try {\n const json = JSON.parse(fileContent);\n fileContent = JSON.stringify(json, null, 2);\n } catch (error) {\n // Just silently fail if the file is not valid JSON\n // Write it as it is\n }\n\n fsSync.writeFileSync(join(dirname(pathToResource), file.fileName), fileContent);\n};\n\nexport const getFileFromResource = async (catalogDir: string, id: string, file: { fileName: string }, version?: string) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory of resource');\n\n const exists = await fs\n .access(join(dirname(pathToResource), file.fileName))\n .then(() => true)\n .catch(() => false);\n if (!exists) throw new Error(`File ${file.fileName} does not exist in resource ${id} v(${version})`);\n\n return fsSync.readFileSync(join(dirname(pathToResource), file.fileName), 'utf-8');\n};\nexport const getVersionedDirectory = (sourceDirectory: string, version: any): string => {\n return join(sourceDirectory, 'versioned', version);\n};\n\nexport const isLatestVersion = async (catalogDir: string, id: string, version?: string) => {\n const resource = await getResource(catalogDir, id, version);\n if (!resource) return false;\n\n const pathToResource = await getResourcePath(catalogDir, id, version);\n\n return !pathToResource?.relativePath.replace(/\\\\/g, '/').includes('/versioned/');\n};\n"],"mappings":"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","names":["import_promises","import_node_path","matter","match","fsSync","import_gray_matter","import_node_fs","import_semver","matter","fsSync","fs","file","fs"]}
1
+ {"version":3,"sources":["../src/events.ts","../src/internal/utils.ts","../src/internal/resources.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { findFileById } from './internal/utils';\nimport type { Event } from './types';\nimport {\n addFileToResource,\n getResource,\n getResourcePath,\n getResources,\n rmResourceById,\n versionResource,\n writeResource,\n} from './internal/resources';\n\n/**\n * Returns an event from EventCatalog.\n *\n * You can optionally specify a version to get a specific version of the event\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvent } = utils('/path/to/eventcatalog');\n *\n * // Gets the latest version of the event\n * const event = await getEvent('InventoryAdjusted');\n *\n * // Gets a version of the event\n * const event = await getEvent('InventoryAdjusted', '0.0.1');\n *\n * // Get the event with the schema attached\n * const event = await getEvent('InventoryAdjusted', '0.0.1', { attachSchema: true });\n * ```\n */\nexport const getEvent =\n (directory: string) =>\n async (id: string, version?: string, options?: { attachSchema?: boolean }): Promise<Event> =>\n getResource(directory, id, version, { type: 'event', ...options }) as Promise<Event>;\n\n/**\n * Returns all events from EventCatalog.\n *\n * You can optionally specify if you want to get the latest version of the events.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvents } = utils('/path/to/eventcatalog');\n *\n * // Gets all events (and versions) from the catalog\n * const events = await getEvents();\n *\n * // Gets all events (only latest version) from the catalog\n * const events = await getEvents({ latestOnly: true });\n *\n * // Get all events with the schema attached\n * const events = await getEvents({ attachSchema: true });\n * ```\n */\nexport const getEvents =\n (directory: string) =>\n async (options?: { latestOnly?: boolean; attachSchema?: boolean }): Promise<Event[]> =>\n getResources(directory, { type: 'events', ...options }) as Promise<Event[]>;\n\n/**\n * Write an event to EventCatalog.\n *\n * You can optionally overide the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEvent } = utils('/path/to/eventcatalog');\n *\n * // Write an event to the catalog\n * // Event would be written to events/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * });\n *\n * // Write an event to the catalog but override the path\n * // Event would be written to events/Inventory/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { path: \"/Inventory/InventoryAdjusted\"});\n *\n * // Write a event to the catalog and override the existing content (if there is any)\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { override: true });\n *\n * // Write a event to the catalog and version the previous version\n * // only works if the new version is greater than the previous version\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { versionExistingContent: true });\n *\n * ```\n */\nexport const writeEvent =\n (directory: string) =>\n async (\n event: Event,\n options: { path?: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n override: false,\n format: 'mdx',\n }\n ) =>\n writeResource(directory, { ...event }, { ...options, type: 'event' });\n/**\n * Write an event to a service in EventCatalog.\n *\n * You can optionally override the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEventToService } = utils('/path/to/eventcatalog');\n *\n * // Write an event to a given service in the catalog\n * // Event would be written to services/Inventory/events/InventoryAdjusted\n * await writeEventToService({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { id: 'Inventory' });\n * ```\n */\nexport const writeEventToService =\n (directory: string) =>\n async (\n event: Event,\n service: { id: string; version?: string },\n options: { path?: string; format?: 'md' | 'mdx'; override?: boolean } = { path: '', format: 'mdx', override: false }\n ) => {\n const resourcePath = await getResourcePath(directory, service.id, service.version);\n if (!resourcePath) {\n throw new Error('Service not found');\n }\n\n let pathForEvent =\n service.version && service.version !== 'latest'\n ? `${resourcePath.directory}/versioned/${service.version}/events`\n : `${resourcePath.directory}/events`;\n pathForEvent = join(pathForEvent, event.id);\n await writeResource(directory, { ...event }, { ...options, path: pathForEvent, type: 'event' });\n };\n\n/**\n * Delete an event at it's given path.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEvent } = utils('/path/to/eventcatalog');\n *\n * // removes an event at the given path (events dir is appended to the given path)\n * // Removes the event at events/InventoryAdjusted\n * await rmEvent('/InventoryAdjusted');\n * ```\n */\nexport const rmEvent = (directory: string) => async (path: string) => {\n await fs.rm(join(directory, path), { recursive: true });\n};\n\n/**\n * Delete an event by it's id.\n *\n * Optionally specify a version to delete a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEventById } = utils('/path/to/eventcatalog');\n *\n * // deletes the latest InventoryAdjusted event\n * await rmEventById('InventoryAdjusted');\n *\n * // deletes a specific version of the InventoryAdjusted event\n * await rmEventById('InventoryAdjusted', '0.0.1');\n * ```\n */\nexport const rmEventById = (directory: string) => async (id: string, version?: string, persistFiles?: boolean) => {\n await rmResourceById(directory, id, version, { type: 'event', persistFiles });\n};\n\n/**\n * Version an event by it's id.\n *\n * Takes the latest event and moves it to a versioned directory.\n * All files with this event are also versioned (e.g /events/InventoryAdjusted/schema.json)\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { versionEvent } = utils('/path/to/eventcatalog');\n *\n * // moves the latest InventoryAdjusted event to a versioned directory\n * // the version within that event is used as the version number.\n * await versionEvent('InventoryAdjusted');\n *\n * ```\n */\nexport const versionEvent = (directory: string) => async (id: string) => versionResource(directory, id);\n\n/**\n * Add a file to an event by it's id.\n *\n * Optionally specify a version to add a file to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' }, '0.0.1');\n *\n * ```\n */\nexport const addFileToEvent =\n (directory: string) => async (id: string, file: { content: string; fileName: string }, version?: string) =>\n addFileToResource(directory, id, file, version);\n\n/**\n * Add a schema to an event by it's id.\n *\n * Optionally specify a version to add a schema to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // JSON schema example\n * const schema = {\n * \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n * \"type\": \"object\",\n * \"properties\": {\n * \"name\": {\n * \"type\": \"string\"\n * },\n * \"age\": {\n * \"type\": \"number\"\n * }\n * },\n * \"required\": [\"name\", \"age\"]\n * };\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' }, '0.0.1');\n *\n * ```\n */\nexport const addSchemaToEvent =\n (directory: string) => async (id: string, schema: { schema: string; fileName: string }, version?: string) => {\n await addFileToEvent(directory)(id, { content: schema.schema, fileName: schema.fileName }, version);\n };\n\n/**\n * Check to see if the catalog has a version for the given event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { eventHasVersion } = utils('/path/to/eventcatalog');\n *\n * // returns true if version is found for the given event and version (supports semver)\n * await eventHasVersion('InventoryAdjusted', '0.0.1');\n * await eventHasVersion('InventoryAdjusted', 'latest');\n * await eventHasVersion('InventoryAdjusted', '0.0.x');*\n *\n * ```\n */\nexport const eventHasVersion = (directory: string) => async (id: string, version?: string) => {\n const file = await findFileById(directory, id, version);\n return !!file;\n};\n","import { globSync } from 'glob';\nimport fsSync from 'node:fs';\nimport { copy, CopyFilterAsync, CopyFilterSync } from 'fs-extra';\nimport { join, dirname, normalize, sep as pathSeparator, resolve, basename, relative } from 'node:path';\nimport matter from 'gray-matter';\nimport { satisfies, validRange, valid } from 'semver';\n\n/**\n * Returns true if a given version of a resource id exists in the catalog\n */\nexport const versionExists = async (catalogDir: string, id: string, version: string) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = (await searchFilesForId(files, id, version)) || [];\n return matchedFiles.length > 0;\n};\n\nexport const findFileById = async (catalogDir: string, id: string, version?: string): Promise<string | undefined> => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = (await searchFilesForId(files, id)) || [];\n const latestVersion = matchedFiles.find((path) => !path.includes('versioned'));\n\n // If no version is provided, return the latest version\n if (!version) {\n return latestVersion;\n }\n\n // map files into gray matter to get versions\n const parsedFiles = matchedFiles.map((path) => {\n const { data } = matter.read(path);\n return { ...data, path };\n }) as any[];\n\n const semverRange = validRange(version);\n\n if (semverRange && valid(version)) {\n const match = parsedFiles.filter((c) => satisfies(c.version, semverRange));\n return match.length > 0 ? match[0].path : undefined;\n }\n\n // Order by version\n const sorted = parsedFiles.sort((a, b) => {\n return a.version.localeCompare(b.version);\n });\n\n // latest version\n const match = sorted.length > 0 ? [sorted[sorted.length - 1]] : [];\n\n if (match.length > 0) {\n return match[0].path;\n }\n};\n\nexport const getFiles = async (pattern: string, ignore: string | string[] = '') => {\n try {\n // 1. Normalize the input pattern to handle mixed separators potentially\n const normalizedInputPattern = normalize(pattern);\n\n // 2. Determine the absolute base directory (cwd for glob)\n // Resolve ensures it's absolute. Handles cases with/without globstar.\n const absoluteBaseDir = resolve(\n normalizedInputPattern.includes('**') ? normalizedInputPattern.split('**')[0] : dirname(normalizedInputPattern)\n );\n\n // 3. Determine the pattern part relative to the absolute base directory\n // We extract the part of the normalized pattern that comes *after* the absoluteBaseDir\n let relativePattern = relative(absoluteBaseDir, normalizedInputPattern);\n\n // On Windows, relative() might return empty string if paths are identical,\n // or might need normalization if the original pattern didn't have `**`\n // Example: pattern = 'dir/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\file.md'\n // relative() -> 'file.md'\n // Example: pattern = 'dir/**/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\**\\file.md'\n // relative() -> '**\\file.md'\n // Convert separators in the relative pattern to forward slashes for glob\n relativePattern = relativePattern.replace(/\\\\/g, '/');\n\n const ignoreList = Array.isArray(ignore) ? ignore : [ignore];\n\n const files = globSync(relativePattern, {\n cwd: absoluteBaseDir,\n ignore: ['node_modules/**', ...ignoreList],\n absolute: true,\n nodir: true,\n });\n\n // 5. Normalize results for consistency before returning\n return files.map(normalize);\n } catch (error: any) {\n // Add more diagnostic info to the error\n const absoluteBaseDirForError = resolve(\n normalize(pattern).includes('**') ? normalize(pattern).split('**')[0] : dirname(normalize(pattern))\n );\n const relativePatternForError = relative(absoluteBaseDirForError, normalize(pattern)).replace(/\\\\/g, '/');\n throw new Error(\n `Error finding files for pattern \"${pattern}\" (using cwd: \"${absoluteBaseDirForError}\", globPattern: \"${relativePatternForError}\"): ${error.message}`\n );\n }\n};\n\nexport const readMdxFile = async (path: string) => {\n const { data } = matter.read(path);\n const { markdown, ...frontmatter } = data;\n return { ...frontmatter, markdown };\n};\n\nexport const searchFilesForId = async (files: string[], id: string, version?: string) => {\n // Escape the id to avoid regex issues\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const idRegex = new RegExp(`^id:\\\\s*(['\"]|>-)?\\\\s*${escapedId}['\"]?\\\\s*$`, 'm');\n\n const versionRegex = new RegExp(`^version:\\\\s*['\"]?${version}['\"]?\\\\s*$`, 'm');\n\n const matches = files.map((file) => {\n const content = fsSync.readFileSync(file, 'utf-8');\n const hasIdMatch = content.match(idRegex);\n\n // Check version if provided\n if (version && !content.match(versionRegex)) {\n return undefined;\n }\n\n if (hasIdMatch) {\n return file;\n }\n });\n\n return matches.filter(Boolean).filter((file) => file !== undefined);\n};\n\n/**\n * Function to copy a directory from source to target, uses a tmp directory\n * @param catalogDir\n * @param source\n * @param target\n * @param filter\n */\nexport const copyDir = async (catalogDir: string, source: string, target: string, filter?: CopyFilterAsync | CopyFilterSync) => {\n const tmpDirectory = join(catalogDir, 'tmp');\n fsSync.mkdirSync(tmpDirectory, { recursive: true });\n\n // Copy everything over\n await copy(source, tmpDirectory, {\n overwrite: true,\n filter,\n });\n\n await copy(tmpDirectory, target, {\n overwrite: true,\n filter,\n });\n\n // Remove the tmp directory\n fsSync.rmSync(tmpDirectory, { recursive: true });\n};\n\n// Makes sure values in sends/recieves are unique\nexport const uniqueVersions = (messages: { id: string; version: string }[]): { id: string; version: string }[] => {\n const uniqueSet = new Set();\n\n return messages.filter((message) => {\n const key = `${message.id}-${message.version}`;\n if (!uniqueSet.has(key)) {\n uniqueSet.add(key);\n return true;\n }\n return false;\n });\n};\n","import { dirname, join } from 'path';\nimport { copyDir, findFileById, getFiles, searchFilesForId, versionExists } from './utils';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport fsSync from 'node:fs';\nimport { Message, Service, CustomDoc } from '../types';\nimport { satisfies } from 'semver';\nimport { lock, unlock } from 'proper-lockfile';\n\ntype Resource = Service | Message | CustomDoc;\n\nexport const versionResource = async (catalogDir: string, id: string) => {\n // Find all the events in the directory\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = await searchFilesForId(files, id);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No resource found with id: ${id}`);\n }\n\n // Event that is in the route of the project\n const file = matchedFiles[0];\n const sourceDirectory = dirname(file);\n const { data: { version = '0.0.1' } = {} } = matter.read(file);\n const targetDirectory = getVersionedDirectory(sourceDirectory, version);\n\n fsSync.mkdirSync(targetDirectory, { recursive: true });\n\n // Copy the event to the versioned directory\n await copyDir(catalogDir, sourceDirectory, targetDirectory, (src) => {\n return !src.includes('versioned');\n });\n\n // Remove all the files in the root of the resource as they have now been versioned\n await fs.readdir(sourceDirectory).then(async (resourceFiles) => {\n await Promise.all(\n resourceFiles.map(async (file) => {\n if (file !== 'versioned') {\n fsSync.rmSync(join(sourceDirectory, file), { recursive: true });\n }\n })\n );\n });\n};\n\nexport const writeResource = async (\n catalogDir: string,\n resource: Resource,\n options: { path?: string; type: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n type: '',\n override: false,\n versionExistingContent: false,\n format: 'mdx',\n }\n) => {\n const path = options.path || `/${resource.id}`;\n const fullPath = join(catalogDir, path);\n const format = options.format || 'mdx';\n\n // Create directory if it doesn't exist\n fsSync.mkdirSync(fullPath, { recursive: true });\n\n // Create or get lock file path\n const lockPath = join(fullPath, `index.${format}`);\n\n // Ensure the file exists before attempting to lock it\n if (!fsSync.existsSync(lockPath)) {\n fsSync.writeFileSync(lockPath, '');\n }\n\n try {\n // Acquire lock with retry\n await lock(lockPath, {\n retries: 5,\n stale: 10000, // 10 seconds\n });\n\n const exists = await versionExists(catalogDir, resource.id, resource.version);\n\n if (exists && !options.override) {\n throw new Error(`Failed to write ${resource.id} (${options.type}) as the version ${resource.version} already exists`);\n }\n\n const { markdown, ...frontmatter } = resource;\n\n if (options.versionExistingContent && !exists) {\n const currentResource = await getResource(catalogDir, resource.id);\n\n if (currentResource) {\n if (satisfies(resource.version, `>${currentResource.version}`)) {\n await versionResource(catalogDir, resource.id);\n } else {\n throw new Error(`New version ${resource.version} is not greater than current version ${currentResource.version}`);\n }\n }\n }\n\n const document = matter.stringify(markdown.trim(), frontmatter);\n fsSync.writeFileSync(lockPath, document);\n } finally {\n // Always release the lock\n await unlock(lockPath).catch(() => {});\n }\n};\n\nexport const getResource = async (\n catalogDir: string,\n id?: string,\n version?: string,\n options?: { type: string; attachSchema?: boolean },\n filePath?: string\n): Promise<Resource | undefined> => {\n const attachSchema = options?.attachSchema || false;\n const file = filePath || (id ? await findFileById(catalogDir, id, version) : undefined);\n if (!file || !fsSync.existsSync(file)) return;\n\n const { data, content } = matter.read(file);\n\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResourcePath = async (catalogDir: string, id: string, version?: string) => {\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n return {\n fullPath: file,\n relativePath: file.replace(catalogDir, ''),\n directory: dirname(file.replace(catalogDir, '')),\n };\n};\n\nexport const toResource = async (catalogDir: string, file: string) => {\n const { data, content } = matter.read(file);\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResources = async (\n catalogDir: string,\n {\n type,\n latestOnly = false,\n ignore = [],\n pattern = '',\n attachSchema = false,\n }: { type: string; pattern?: string; latestOnly?: boolean; ignore?: string[]; attachSchema?: boolean }\n): Promise<Resource[] | undefined> => {\n const ignoreList = latestOnly ? `**/versioned/**` : '';\n const filePattern = pattern || `${catalogDir}/**/${type}/**/index.{md,mdx}`;\n const files = await getFiles(filePattern, [ignoreList, ...ignore]);\n\n if (files.length === 0) return;\n\n return files.map((file) => {\n const { data, content } = matter.read(file);\n\n // Attach the schema if the attachSchema option is set to true\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n });\n};\n\nexport const rmResourceById = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; persistFiles?: boolean }\n) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = await searchFilesForId(files, id, version);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No ${options?.type || 'resource'} found with id: ${id}`);\n }\n\n if (options?.persistFiles) {\n await Promise.all(\n matchedFiles.map(async (file) => {\n await fs.rm(file, { recursive: true });\n })\n );\n } else {\n await Promise.all(\n matchedFiles.map(async (file) => {\n const directory = dirname(file);\n await fs.rm(directory, { recursive: true, force: true });\n })\n );\n }\n};\n\nexport const addFileToResource = async (\n catalogDir: string,\n id: string,\n file: { content: string; fileName: string },\n version?: string\n) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory to write file to');\n\n let fileContent = file.content.trim();\n\n try {\n const json = JSON.parse(fileContent);\n fileContent = JSON.stringify(json, null, 2);\n } catch (error) {\n // Just silently fail if the file is not valid JSON\n // Write it as it is\n }\n\n fsSync.writeFileSync(join(dirname(pathToResource), file.fileName), fileContent);\n};\n\nexport const getFileFromResource = async (catalogDir: string, id: string, file: { fileName: string }, version?: string) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory of resource');\n\n const exists = await fs\n .access(join(dirname(pathToResource), file.fileName))\n .then(() => true)\n .catch(() => false);\n if (!exists) throw new Error(`File ${file.fileName} does not exist in resource ${id} v(${version})`);\n\n return fsSync.readFileSync(join(dirname(pathToResource), file.fileName), 'utf-8');\n};\nexport const getVersionedDirectory = (sourceDirectory: string, version: any): string => {\n return join(sourceDirectory, 'versioned', version);\n};\n\nexport const isLatestVersion = async (catalogDir: string, id: string, version?: string) => {\n const resource = await getResource(catalogDir, id, version);\n if (!resource) return false;\n\n const pathToResource = await getResourcePath(catalogDir, id, version);\n\n return !pathToResource?.relativePath.replace(/\\\\/g, '/').includes('/versioned/');\n};\n"],"mappings":"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","names":["import_promises","import_node_path","matter","match","fsSync","import_gray_matter","import_node_fs","import_semver","matter","fsSync","fs","file","matter","fsSync","fs","fs"]}
package/dist/events.mjs CHANGED
@@ -168,10 +168,10 @@ var writeResource = async (catalogDir, resource, options = {
168
168
  });
169
169
  }
170
170
  };
171
- var getResource = async (catalogDir, id, version, options) => {
171
+ var getResource = async (catalogDir, id, version, options, filePath) => {
172
172
  const attachSchema = options?.attachSchema || false;
173
- const file = await findFileById(catalogDir, id, version);
174
- if (!file) return;
173
+ const file = filePath || (id ? await findFileById(catalogDir, id, version) : void 0);
174
+ if (!file || !fsSync2.existsSync(file)) return;
175
175
  const { data, content } = matter2.read(file);
176
176
  if (attachSchema && data?.schemaPath) {
177
177
  const resourceDirectory = dirname2(file);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/internal/utils.ts","../src/internal/resources.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { findFileById } from './internal/utils';\nimport type { Event } from './types';\nimport {\n addFileToResource,\n getResource,\n getResourcePath,\n getResources,\n rmResourceById,\n versionResource,\n writeResource,\n} from './internal/resources';\n\n/**\n * Returns an event from EventCatalog.\n *\n * You can optionally specify a version to get a specific version of the event\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvent } = utils('/path/to/eventcatalog');\n *\n * // Gets the latest version of the event\n * const event = await getEvent('InventoryAdjusted');\n *\n * // Gets a version of the event\n * const event = await getEvent('InventoryAdjusted', '0.0.1');\n *\n * // Get the event with the schema attached\n * const event = await getEvent('InventoryAdjusted', '0.0.1', { attachSchema: true });\n * ```\n */\nexport const getEvent =\n (directory: string) =>\n async (id: string, version?: string, options?: { attachSchema?: boolean }): Promise<Event> =>\n getResource(directory, id, version, { type: 'event', ...options }) as Promise<Event>;\n\n/**\n * Returns all events from EventCatalog.\n *\n * You can optionally specify if you want to get the latest version of the events.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvents } = utils('/path/to/eventcatalog');\n *\n * // Gets all events (and versions) from the catalog\n * const events = await getEvents();\n *\n * // Gets all events (only latest version) from the catalog\n * const events = await getEvents({ latestOnly: true });\n *\n * // Get all events with the schema attached\n * const events = await getEvents({ attachSchema: true });\n * ```\n */\nexport const getEvents =\n (directory: string) =>\n async (options?: { latestOnly?: boolean; attachSchema?: boolean }): Promise<Event[]> =>\n getResources(directory, { type: 'events', ...options }) as Promise<Event[]>;\n\n/**\n * Write an event to EventCatalog.\n *\n * You can optionally overide the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEvent } = utils('/path/to/eventcatalog');\n *\n * // Write an event to the catalog\n * // Event would be written to events/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * });\n *\n * // Write an event to the catalog but override the path\n * // Event would be written to events/Inventory/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { path: \"/Inventory/InventoryAdjusted\"});\n *\n * // Write a event to the catalog and override the existing content (if there is any)\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { override: true });\n *\n * // Write a event to the catalog and version the previous version\n * // only works if the new version is greater than the previous version\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { versionExistingContent: true });\n *\n * ```\n */\nexport const writeEvent =\n (directory: string) =>\n async (\n event: Event,\n options: { path?: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n override: false,\n format: 'mdx',\n }\n ) =>\n writeResource(directory, { ...event }, { ...options, type: 'event' });\n/**\n * Write an event to a service in EventCatalog.\n *\n * You can optionally override the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEventToService } = utils('/path/to/eventcatalog');\n *\n * // Write an event to a given service in the catalog\n * // Event would be written to services/Inventory/events/InventoryAdjusted\n * await writeEventToService({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { id: 'Inventory' });\n * ```\n */\nexport const writeEventToService =\n (directory: string) =>\n async (\n event: Event,\n service: { id: string; version?: string },\n options: { path?: string; format?: 'md' | 'mdx'; override?: boolean } = { path: '', format: 'mdx', override: false }\n ) => {\n const resourcePath = await getResourcePath(directory, service.id, service.version);\n if (!resourcePath) {\n throw new Error('Service not found');\n }\n\n let pathForEvent =\n service.version && service.version !== 'latest'\n ? `${resourcePath.directory}/versioned/${service.version}/events`\n : `${resourcePath.directory}/events`;\n pathForEvent = join(pathForEvent, event.id);\n await writeResource(directory, { ...event }, { ...options, path: pathForEvent, type: 'event' });\n };\n\n/**\n * Delete an event at it's given path.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEvent } = utils('/path/to/eventcatalog');\n *\n * // removes an event at the given path (events dir is appended to the given path)\n * // Removes the event at events/InventoryAdjusted\n * await rmEvent('/InventoryAdjusted');\n * ```\n */\nexport const rmEvent = (directory: string) => async (path: string) => {\n await fs.rm(join(directory, path), { recursive: true });\n};\n\n/**\n * Delete an event by it's id.\n *\n * Optionally specify a version to delete a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEventById } = utils('/path/to/eventcatalog');\n *\n * // deletes the latest InventoryAdjusted event\n * await rmEventById('InventoryAdjusted');\n *\n * // deletes a specific version of the InventoryAdjusted event\n * await rmEventById('InventoryAdjusted', '0.0.1');\n * ```\n */\nexport const rmEventById = (directory: string) => async (id: string, version?: string, persistFiles?: boolean) => {\n await rmResourceById(directory, id, version, { type: 'event', persistFiles });\n};\n\n/**\n * Version an event by it's id.\n *\n * Takes the latest event and moves it to a versioned directory.\n * All files with this event are also versioned (e.g /events/InventoryAdjusted/schema.json)\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { versionEvent } = utils('/path/to/eventcatalog');\n *\n * // moves the latest InventoryAdjusted event to a versioned directory\n * // the version within that event is used as the version number.\n * await versionEvent('InventoryAdjusted');\n *\n * ```\n */\nexport const versionEvent = (directory: string) => async (id: string) => versionResource(directory, id);\n\n/**\n * Add a file to an event by it's id.\n *\n * Optionally specify a version to add a file to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' }, '0.0.1');\n *\n * ```\n */\nexport const addFileToEvent =\n (directory: string) => async (id: string, file: { content: string; fileName: string }, version?: string) =>\n addFileToResource(directory, id, file, version);\n\n/**\n * Add a schema to an event by it's id.\n *\n * Optionally specify a version to add a schema to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // JSON schema example\n * const schema = {\n * \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n * \"type\": \"object\",\n * \"properties\": {\n * \"name\": {\n * \"type\": \"string\"\n * },\n * \"age\": {\n * \"type\": \"number\"\n * }\n * },\n * \"required\": [\"name\", \"age\"]\n * };\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' }, '0.0.1');\n *\n * ```\n */\nexport const addSchemaToEvent =\n (directory: string) => async (id: string, schema: { schema: string; fileName: string }, version?: string) => {\n await addFileToEvent(directory)(id, { content: schema.schema, fileName: schema.fileName }, version);\n };\n\n/**\n * Check to see if the catalog has a version for the given event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { eventHasVersion } = utils('/path/to/eventcatalog');\n *\n * // returns true if version is found for the given event and version (supports semver)\n * await eventHasVersion('InventoryAdjusted', '0.0.1');\n * await eventHasVersion('InventoryAdjusted', 'latest');\n * await eventHasVersion('InventoryAdjusted', '0.0.x');*\n *\n * ```\n */\nexport const eventHasVersion = (directory: string) => async (id: string, version?: string) => {\n const file = await findFileById(directory, id, version);\n return !!file;\n};\n","import { globSync } from 'glob';\nimport fsSync from 'node:fs';\nimport { copy, CopyFilterAsync, CopyFilterSync } from 'fs-extra';\nimport { join, dirname, normalize, sep as pathSeparator, resolve, basename, relative } from 'node:path';\nimport matter from 'gray-matter';\nimport { satisfies, validRange, valid } from 'semver';\n\n/**\n * Returns true if a given version of a resource id exists in the catalog\n */\nexport const versionExists = async (catalogDir: string, id: string, version: string) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = (await searchFilesForId(files, id, version)) || [];\n return matchedFiles.length > 0;\n};\n\nexport const findFileById = async (catalogDir: string, id: string, version?: string): Promise<string | undefined> => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = (await searchFilesForId(files, id)) || [];\n const latestVersion = matchedFiles.find((path) => !path.includes('versioned'));\n\n // If no version is provided, return the latest version\n if (!version) {\n return latestVersion;\n }\n\n // map files into gray matter to get versions\n const parsedFiles = matchedFiles.map((path) => {\n const { data } = matter.read(path);\n return { ...data, path };\n }) as any[];\n\n const semverRange = validRange(version);\n\n if (semverRange && valid(version)) {\n const match = parsedFiles.filter((c) => satisfies(c.version, semverRange));\n return match.length > 0 ? match[0].path : undefined;\n }\n\n // Order by version\n const sorted = parsedFiles.sort((a, b) => {\n return a.version.localeCompare(b.version);\n });\n\n // latest version\n const match = sorted.length > 0 ? [sorted[sorted.length - 1]] : [];\n\n if (match.length > 0) {\n return match[0].path;\n }\n};\n\nexport const getFiles = async (pattern: string, ignore: string | string[] = '') => {\n try {\n // 1. Normalize the input pattern to handle mixed separators potentially\n const normalizedInputPattern = normalize(pattern);\n\n // 2. Determine the absolute base directory (cwd for glob)\n // Resolve ensures it's absolute. Handles cases with/without globstar.\n const absoluteBaseDir = resolve(\n normalizedInputPattern.includes('**') ? normalizedInputPattern.split('**')[0] : dirname(normalizedInputPattern)\n );\n\n // 3. Determine the pattern part relative to the absolute base directory\n // We extract the part of the normalized pattern that comes *after* the absoluteBaseDir\n let relativePattern = relative(absoluteBaseDir, normalizedInputPattern);\n\n // On Windows, relative() might return empty string if paths are identical,\n // or might need normalization if the original pattern didn't have `**`\n // Example: pattern = 'dir/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\file.md'\n // relative() -> 'file.md'\n // Example: pattern = 'dir/**/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\**\\file.md'\n // relative() -> '**\\file.md'\n // Convert separators in the relative pattern to forward slashes for glob\n relativePattern = relativePattern.replace(/\\\\/g, '/');\n\n const ignoreList = Array.isArray(ignore) ? ignore : [ignore];\n\n const files = globSync(relativePattern, {\n cwd: absoluteBaseDir,\n ignore: ['node_modules/**', ...ignoreList],\n absolute: true,\n nodir: true,\n });\n\n // 5. Normalize results for consistency before returning\n return files.map(normalize);\n } catch (error: any) {\n // Add more diagnostic info to the error\n const absoluteBaseDirForError = resolve(\n normalize(pattern).includes('**') ? normalize(pattern).split('**')[0] : dirname(normalize(pattern))\n );\n const relativePatternForError = relative(absoluteBaseDirForError, normalize(pattern)).replace(/\\\\/g, '/');\n throw new Error(\n `Error finding files for pattern \"${pattern}\" (using cwd: \"${absoluteBaseDirForError}\", globPattern: \"${relativePatternForError}\"): ${error.message}`\n );\n }\n};\n\nexport const readMdxFile = async (path: string) => {\n const { data } = matter.read(path);\n const { markdown, ...frontmatter } = data;\n return { ...frontmatter, markdown };\n};\n\nexport const searchFilesForId = async (files: string[], id: string, version?: string) => {\n // Escape the id to avoid regex issues\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const idRegex = new RegExp(`^id:\\\\s*(['\"]|>-)?\\\\s*${escapedId}['\"]?\\\\s*$`, 'm');\n\n const versionRegex = new RegExp(`^version:\\\\s*['\"]?${version}['\"]?\\\\s*$`, 'm');\n\n const matches = files.map((file) => {\n const content = fsSync.readFileSync(file, 'utf-8');\n const hasIdMatch = content.match(idRegex);\n\n // Check version if provided\n if (version && !content.match(versionRegex)) {\n return undefined;\n }\n\n if (hasIdMatch) {\n return file;\n }\n });\n\n return matches.filter(Boolean).filter((file) => file !== undefined);\n};\n\n/**\n * Function to copy a directory from source to target, uses a tmp directory\n * @param catalogDir\n * @param source\n * @param target\n * @param filter\n */\nexport const copyDir = async (catalogDir: string, source: string, target: string, filter?: CopyFilterAsync | CopyFilterSync) => {\n const tmpDirectory = join(catalogDir, 'tmp');\n fsSync.mkdirSync(tmpDirectory, { recursive: true });\n\n // Copy everything over\n await copy(source, tmpDirectory, {\n overwrite: true,\n filter,\n });\n\n await copy(tmpDirectory, target, {\n overwrite: true,\n filter,\n });\n\n // Remove the tmp directory\n fsSync.rmSync(tmpDirectory, { recursive: true });\n};\n\n// Makes sure values in sends/recieves are unique\nexport const uniqueVersions = (messages: { id: string; version: string }[]): { id: string; version: string }[] => {\n const uniqueSet = new Set();\n\n return messages.filter((message) => {\n const key = `${message.id}-${message.version}`;\n if (!uniqueSet.has(key)) {\n uniqueSet.add(key);\n return true;\n }\n return false;\n });\n};\n","import { dirname, join } from 'path';\nimport { copyDir, findFileById, getFiles, searchFilesForId, versionExists } from './utils';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport fsSync from 'node:fs';\nimport { Message, Service, CustomDoc } from '../types';\nimport { satisfies } from 'semver';\nimport { lock, unlock } from 'proper-lockfile';\n\ntype Resource = Service | Message | CustomDoc;\n\nexport const versionResource = async (catalogDir: string, id: string) => {\n // Find all the events in the directory\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = await searchFilesForId(files, id);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No resource found with id: ${id}`);\n }\n\n // Event that is in the route of the project\n const file = matchedFiles[0];\n const sourceDirectory = dirname(file);\n const { data: { version = '0.0.1' } = {} } = matter.read(file);\n const targetDirectory = getVersionedDirectory(sourceDirectory, version);\n\n fsSync.mkdirSync(targetDirectory, { recursive: true });\n\n // Copy the event to the versioned directory\n await copyDir(catalogDir, sourceDirectory, targetDirectory, (src) => {\n return !src.includes('versioned');\n });\n\n // Remove all the files in the root of the resource as they have now been versioned\n await fs.readdir(sourceDirectory).then(async (resourceFiles) => {\n await Promise.all(\n resourceFiles.map(async (file) => {\n if (file !== 'versioned') {\n fsSync.rmSync(join(sourceDirectory, file), { recursive: true });\n }\n })\n );\n });\n};\n\nexport const writeResource = async (\n catalogDir: string,\n resource: Resource,\n options: { path?: string; type: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n type: '',\n override: false,\n versionExistingContent: false,\n format: 'mdx',\n }\n) => {\n const path = options.path || `/${resource.id}`;\n const fullPath = join(catalogDir, path);\n const format = options.format || 'mdx';\n\n // Create directory if it doesn't exist\n fsSync.mkdirSync(fullPath, { recursive: true });\n\n // Create or get lock file path\n const lockPath = join(fullPath, `index.${format}`);\n\n // Ensure the file exists before attempting to lock it\n if (!fsSync.existsSync(lockPath)) {\n fsSync.writeFileSync(lockPath, '');\n }\n\n try {\n // Acquire lock with retry\n await lock(lockPath, {\n retries: 5,\n stale: 10000, // 10 seconds\n });\n\n const exists = await versionExists(catalogDir, resource.id, resource.version);\n\n if (exists && !options.override) {\n throw new Error(`Failed to write ${resource.id} (${options.type}) as the version ${resource.version} already exists`);\n }\n\n const { markdown, ...frontmatter } = resource;\n\n if (options.versionExistingContent && !exists) {\n const currentResource = await getResource(catalogDir, resource.id);\n\n if (currentResource) {\n if (satisfies(resource.version, `>${currentResource.version}`)) {\n await versionResource(catalogDir, resource.id);\n } else {\n throw new Error(`New version ${resource.version} is not greater than current version ${currentResource.version}`);\n }\n }\n }\n\n const document = matter.stringify(markdown.trim(), frontmatter);\n fsSync.writeFileSync(lockPath, document);\n } finally {\n // Always release the lock\n await unlock(lockPath).catch(() => {});\n }\n};\n\nexport const getResource = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; attachSchema?: boolean }\n): Promise<Resource | undefined> => {\n const attachSchema = options?.attachSchema || false;\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n const { data, content } = matter.read(file);\n\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResourcePath = async (catalogDir: string, id: string, version?: string) => {\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n return {\n fullPath: file,\n relativePath: file.replace(catalogDir, ''),\n directory: dirname(file.replace(catalogDir, '')),\n };\n};\n\nexport const getResources = async (\n catalogDir: string,\n {\n type,\n latestOnly = false,\n ignore = [],\n pattern = '',\n attachSchema = false,\n }: { type: string; pattern?: string; latestOnly?: boolean; ignore?: string[]; attachSchema?: boolean }\n): Promise<Resource[] | undefined> => {\n const ignoreList = latestOnly ? `**/versioned/**` : '';\n const filePattern = pattern || `${catalogDir}/**/${type}/**/index.{md,mdx}`;\n const files = await getFiles(filePattern, [ignoreList, ...ignore]);\n\n if (files.length === 0) return;\n\n return files.map((file) => {\n const { data, content } = matter.read(file);\n\n // Attach the schema if the attachSchema option is set to true\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n });\n};\n\nexport const rmResourceById = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; persistFiles?: boolean }\n) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = await searchFilesForId(files, id, version);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No ${options?.type || 'resource'} found with id: ${id}`);\n }\n\n if (options?.persistFiles) {\n await Promise.all(\n matchedFiles.map(async (file) => {\n await fs.rm(file, { recursive: true });\n })\n );\n } else {\n await Promise.all(\n matchedFiles.map(async (file) => {\n const directory = dirname(file);\n await fs.rm(directory, { recursive: true, force: true });\n })\n );\n }\n};\n\nexport const addFileToResource = async (\n catalogDir: string,\n id: string,\n file: { content: string; fileName: string },\n version?: string\n) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory to write file to');\n\n let fileContent = file.content.trim();\n\n try {\n const json = JSON.parse(fileContent);\n fileContent = JSON.stringify(json, null, 2);\n } catch (error) {\n // Just silently fail if the file is not valid JSON\n // Write it as it is\n }\n\n fsSync.writeFileSync(join(dirname(pathToResource), file.fileName), fileContent);\n};\n\nexport const getFileFromResource = async (catalogDir: string, id: string, file: { fileName: string }, version?: string) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory of resource');\n\n const exists = await fs\n .access(join(dirname(pathToResource), file.fileName))\n .then(() => true)\n .catch(() => false);\n if (!exists) throw new Error(`File ${file.fileName} does not exist in resource ${id} v(${version})`);\n\n return fsSync.readFileSync(join(dirname(pathToResource), file.fileName), 'utf-8');\n};\nexport const getVersionedDirectory = (sourceDirectory: string, version: any): string => {\n return join(sourceDirectory, 'versioned', version);\n};\n\nexport const isLatestVersion = async (catalogDir: string, id: string, version?: string) => {\n const resource = await getResource(catalogDir, id, version);\n if (!resource) return false;\n\n const pathToResource = await getResourcePath(catalogDir, id, version);\n\n return !pathToResource?.relativePath.replace(/\\\\/g, '/').includes('/versioned/');\n};\n"],"mappings":"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","names":["fs","join","match","dirname","join","matter","fsSync","satisfies","dirname","file","join","join","join","fs"]}
1
+ {"version":3,"sources":["../src/events.ts","../src/internal/utils.ts","../src/internal/resources.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { findFileById } from './internal/utils';\nimport type { Event } from './types';\nimport {\n addFileToResource,\n getResource,\n getResourcePath,\n getResources,\n rmResourceById,\n versionResource,\n writeResource,\n} from './internal/resources';\n\n/**\n * Returns an event from EventCatalog.\n *\n * You can optionally specify a version to get a specific version of the event\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvent } = utils('/path/to/eventcatalog');\n *\n * // Gets the latest version of the event\n * const event = await getEvent('InventoryAdjusted');\n *\n * // Gets a version of the event\n * const event = await getEvent('InventoryAdjusted', '0.0.1');\n *\n * // Get the event with the schema attached\n * const event = await getEvent('InventoryAdjusted', '0.0.1', { attachSchema: true });\n * ```\n */\nexport const getEvent =\n (directory: string) =>\n async (id: string, version?: string, options?: { attachSchema?: boolean }): Promise<Event> =>\n getResource(directory, id, version, { type: 'event', ...options }) as Promise<Event>;\n\n/**\n * Returns all events from EventCatalog.\n *\n * You can optionally specify if you want to get the latest version of the events.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { getEvents } = utils('/path/to/eventcatalog');\n *\n * // Gets all events (and versions) from the catalog\n * const events = await getEvents();\n *\n * // Gets all events (only latest version) from the catalog\n * const events = await getEvents({ latestOnly: true });\n *\n * // Get all events with the schema attached\n * const events = await getEvents({ attachSchema: true });\n * ```\n */\nexport const getEvents =\n (directory: string) =>\n async (options?: { latestOnly?: boolean; attachSchema?: boolean }): Promise<Event[]> =>\n getResources(directory, { type: 'events', ...options }) as Promise<Event[]>;\n\n/**\n * Write an event to EventCatalog.\n *\n * You can optionally overide the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEvent } = utils('/path/to/eventcatalog');\n *\n * // Write an event to the catalog\n * // Event would be written to events/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * });\n *\n * // Write an event to the catalog but override the path\n * // Event would be written to events/Inventory/InventoryAdjusted\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { path: \"/Inventory/InventoryAdjusted\"});\n *\n * // Write a event to the catalog and override the existing content (if there is any)\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { override: true });\n *\n * // Write a event to the catalog and version the previous version\n * // only works if the new version is greater than the previous version\n * await writeEvent({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { versionExistingContent: true });\n *\n * ```\n */\nexport const writeEvent =\n (directory: string) =>\n async (\n event: Event,\n options: { path?: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n override: false,\n format: 'mdx',\n }\n ) =>\n writeResource(directory, { ...event }, { ...options, type: 'event' });\n/**\n * Write an event to a service in EventCatalog.\n *\n * You can optionally override the path of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { writeEventToService } = utils('/path/to/eventcatalog');\n *\n * // Write an event to a given service in the catalog\n * // Event would be written to services/Inventory/events/InventoryAdjusted\n * await writeEventToService({\n * id: 'InventoryAdjusted',\n * name: 'Inventory Adjusted',\n * version: '0.0.1',\n * summary: 'This is a summary',\n * markdown: '# Hello world',\n * }, { id: 'Inventory' });\n * ```\n */\nexport const writeEventToService =\n (directory: string) =>\n async (\n event: Event,\n service: { id: string; version?: string },\n options: { path?: string; format?: 'md' | 'mdx'; override?: boolean } = { path: '', format: 'mdx', override: false }\n ) => {\n const resourcePath = await getResourcePath(directory, service.id, service.version);\n if (!resourcePath) {\n throw new Error('Service not found');\n }\n\n let pathForEvent =\n service.version && service.version !== 'latest'\n ? `${resourcePath.directory}/versioned/${service.version}/events`\n : `${resourcePath.directory}/events`;\n pathForEvent = join(pathForEvent, event.id);\n await writeResource(directory, { ...event }, { ...options, path: pathForEvent, type: 'event' });\n };\n\n/**\n * Delete an event at it's given path.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEvent } = utils('/path/to/eventcatalog');\n *\n * // removes an event at the given path (events dir is appended to the given path)\n * // Removes the event at events/InventoryAdjusted\n * await rmEvent('/InventoryAdjusted');\n * ```\n */\nexport const rmEvent = (directory: string) => async (path: string) => {\n await fs.rm(join(directory, path), { recursive: true });\n};\n\n/**\n * Delete an event by it's id.\n *\n * Optionally specify a version to delete a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { rmEventById } = utils('/path/to/eventcatalog');\n *\n * // deletes the latest InventoryAdjusted event\n * await rmEventById('InventoryAdjusted');\n *\n * // deletes a specific version of the InventoryAdjusted event\n * await rmEventById('InventoryAdjusted', '0.0.1');\n * ```\n */\nexport const rmEventById = (directory: string) => async (id: string, version?: string, persistFiles?: boolean) => {\n await rmResourceById(directory, id, version, { type: 'event', persistFiles });\n};\n\n/**\n * Version an event by it's id.\n *\n * Takes the latest event and moves it to a versioned directory.\n * All files with this event are also versioned (e.g /events/InventoryAdjusted/schema.json)\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { versionEvent } = utils('/path/to/eventcatalog');\n *\n * // moves the latest InventoryAdjusted event to a versioned directory\n * // the version within that event is used as the version number.\n * await versionEvent('InventoryAdjusted');\n *\n * ```\n */\nexport const versionEvent = (directory: string) => async (id: string) => versionResource(directory, id);\n\n/**\n * Add a file to an event by it's id.\n *\n * Optionally specify a version to add a file to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { content: 'Hello world', fileName: 'hello.txt' }, '0.0.1');\n *\n * ```\n */\nexport const addFileToEvent =\n (directory: string) => async (id: string, file: { content: string; fileName: string }, version?: string) =>\n addFileToResource(directory, id, file, version);\n\n/**\n * Add a schema to an event by it's id.\n *\n * Optionally specify a version to add a schema to a specific version of the event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { addFileToEvent } = utils('/path/to/eventcatalog');\n *\n * // JSON schema example\n * const schema = {\n * \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n * \"type\": \"object\",\n * \"properties\": {\n * \"name\": {\n * \"type\": \"string\"\n * },\n * \"age\": {\n * \"type\": \"number\"\n * }\n * },\n * \"required\": [\"name\", \"age\"]\n * };\n *\n * // adds a file to the latest InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' });\n *\n * // adds a file to a specific version of the InventoryAdjusted event\n * await addFileToEvent('InventoryAdjusted', { schema, fileName: 'schema.json' }, '0.0.1');\n *\n * ```\n */\nexport const addSchemaToEvent =\n (directory: string) => async (id: string, schema: { schema: string; fileName: string }, version?: string) => {\n await addFileToEvent(directory)(id, { content: schema.schema, fileName: schema.fileName }, version);\n };\n\n/**\n * Check to see if the catalog has a version for the given event.\n *\n * @example\n * ```ts\n * import utils from '@eventcatalog/utils';\n *\n * const { eventHasVersion } = utils('/path/to/eventcatalog');\n *\n * // returns true if version is found for the given event and version (supports semver)\n * await eventHasVersion('InventoryAdjusted', '0.0.1');\n * await eventHasVersion('InventoryAdjusted', 'latest');\n * await eventHasVersion('InventoryAdjusted', '0.0.x');*\n *\n * ```\n */\nexport const eventHasVersion = (directory: string) => async (id: string, version?: string) => {\n const file = await findFileById(directory, id, version);\n return !!file;\n};\n","import { globSync } from 'glob';\nimport fsSync from 'node:fs';\nimport { copy, CopyFilterAsync, CopyFilterSync } from 'fs-extra';\nimport { join, dirname, normalize, sep as pathSeparator, resolve, basename, relative } from 'node:path';\nimport matter from 'gray-matter';\nimport { satisfies, validRange, valid } from 'semver';\n\n/**\n * Returns true if a given version of a resource id exists in the catalog\n */\nexport const versionExists = async (catalogDir: string, id: string, version: string) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = (await searchFilesForId(files, id, version)) || [];\n return matchedFiles.length > 0;\n};\n\nexport const findFileById = async (catalogDir: string, id: string, version?: string): Promise<string | undefined> => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = (await searchFilesForId(files, id)) || [];\n const latestVersion = matchedFiles.find((path) => !path.includes('versioned'));\n\n // If no version is provided, return the latest version\n if (!version) {\n return latestVersion;\n }\n\n // map files into gray matter to get versions\n const parsedFiles = matchedFiles.map((path) => {\n const { data } = matter.read(path);\n return { ...data, path };\n }) as any[];\n\n const semverRange = validRange(version);\n\n if (semverRange && valid(version)) {\n const match = parsedFiles.filter((c) => satisfies(c.version, semverRange));\n return match.length > 0 ? match[0].path : undefined;\n }\n\n // Order by version\n const sorted = parsedFiles.sort((a, b) => {\n return a.version.localeCompare(b.version);\n });\n\n // latest version\n const match = sorted.length > 0 ? [sorted[sorted.length - 1]] : [];\n\n if (match.length > 0) {\n return match[0].path;\n }\n};\n\nexport const getFiles = async (pattern: string, ignore: string | string[] = '') => {\n try {\n // 1. Normalize the input pattern to handle mixed separators potentially\n const normalizedInputPattern = normalize(pattern);\n\n // 2. Determine the absolute base directory (cwd for glob)\n // Resolve ensures it's absolute. Handles cases with/without globstar.\n const absoluteBaseDir = resolve(\n normalizedInputPattern.includes('**') ? normalizedInputPattern.split('**')[0] : dirname(normalizedInputPattern)\n );\n\n // 3. Determine the pattern part relative to the absolute base directory\n // We extract the part of the normalized pattern that comes *after* the absoluteBaseDir\n let relativePattern = relative(absoluteBaseDir, normalizedInputPattern);\n\n // On Windows, relative() might return empty string if paths are identical,\n // or might need normalization if the original pattern didn't have `**`\n // Example: pattern = 'dir/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\file.md'\n // relative() -> 'file.md'\n // Example: pattern = 'dir/**/file.md', absoluteBaseDir='.../dir', normalized='...\\dir\\**\\file.md'\n // relative() -> '**\\file.md'\n // Convert separators in the relative pattern to forward slashes for glob\n relativePattern = relativePattern.replace(/\\\\/g, '/');\n\n const ignoreList = Array.isArray(ignore) ? ignore : [ignore];\n\n const files = globSync(relativePattern, {\n cwd: absoluteBaseDir,\n ignore: ['node_modules/**', ...ignoreList],\n absolute: true,\n nodir: true,\n });\n\n // 5. Normalize results for consistency before returning\n return files.map(normalize);\n } catch (error: any) {\n // Add more diagnostic info to the error\n const absoluteBaseDirForError = resolve(\n normalize(pattern).includes('**') ? normalize(pattern).split('**')[0] : dirname(normalize(pattern))\n );\n const relativePatternForError = relative(absoluteBaseDirForError, normalize(pattern)).replace(/\\\\/g, '/');\n throw new Error(\n `Error finding files for pattern \"${pattern}\" (using cwd: \"${absoluteBaseDirForError}\", globPattern: \"${relativePatternForError}\"): ${error.message}`\n );\n }\n};\n\nexport const readMdxFile = async (path: string) => {\n const { data } = matter.read(path);\n const { markdown, ...frontmatter } = data;\n return { ...frontmatter, markdown };\n};\n\nexport const searchFilesForId = async (files: string[], id: string, version?: string) => {\n // Escape the id to avoid regex issues\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const idRegex = new RegExp(`^id:\\\\s*(['\"]|>-)?\\\\s*${escapedId}['\"]?\\\\s*$`, 'm');\n\n const versionRegex = new RegExp(`^version:\\\\s*['\"]?${version}['\"]?\\\\s*$`, 'm');\n\n const matches = files.map((file) => {\n const content = fsSync.readFileSync(file, 'utf-8');\n const hasIdMatch = content.match(idRegex);\n\n // Check version if provided\n if (version && !content.match(versionRegex)) {\n return undefined;\n }\n\n if (hasIdMatch) {\n return file;\n }\n });\n\n return matches.filter(Boolean).filter((file) => file !== undefined);\n};\n\n/**\n * Function to copy a directory from source to target, uses a tmp directory\n * @param catalogDir\n * @param source\n * @param target\n * @param filter\n */\nexport const copyDir = async (catalogDir: string, source: string, target: string, filter?: CopyFilterAsync | CopyFilterSync) => {\n const tmpDirectory = join(catalogDir, 'tmp');\n fsSync.mkdirSync(tmpDirectory, { recursive: true });\n\n // Copy everything over\n await copy(source, tmpDirectory, {\n overwrite: true,\n filter,\n });\n\n await copy(tmpDirectory, target, {\n overwrite: true,\n filter,\n });\n\n // Remove the tmp directory\n fsSync.rmSync(tmpDirectory, { recursive: true });\n};\n\n// Makes sure values in sends/recieves are unique\nexport const uniqueVersions = (messages: { id: string; version: string }[]): { id: string; version: string }[] => {\n const uniqueSet = new Set();\n\n return messages.filter((message) => {\n const key = `${message.id}-${message.version}`;\n if (!uniqueSet.has(key)) {\n uniqueSet.add(key);\n return true;\n }\n return false;\n });\n};\n","import { dirname, join } from 'path';\nimport { copyDir, findFileById, getFiles, searchFilesForId, versionExists } from './utils';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport fsSync from 'node:fs';\nimport { Message, Service, CustomDoc } from '../types';\nimport { satisfies } from 'semver';\nimport { lock, unlock } from 'proper-lockfile';\n\ntype Resource = Service | Message | CustomDoc;\n\nexport const versionResource = async (catalogDir: string, id: string) => {\n // Find all the events in the directory\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n const matchedFiles = await searchFilesForId(files, id);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No resource found with id: ${id}`);\n }\n\n // Event that is in the route of the project\n const file = matchedFiles[0];\n const sourceDirectory = dirname(file);\n const { data: { version = '0.0.1' } = {} } = matter.read(file);\n const targetDirectory = getVersionedDirectory(sourceDirectory, version);\n\n fsSync.mkdirSync(targetDirectory, { recursive: true });\n\n // Copy the event to the versioned directory\n await copyDir(catalogDir, sourceDirectory, targetDirectory, (src) => {\n return !src.includes('versioned');\n });\n\n // Remove all the files in the root of the resource as they have now been versioned\n await fs.readdir(sourceDirectory).then(async (resourceFiles) => {\n await Promise.all(\n resourceFiles.map(async (file) => {\n if (file !== 'versioned') {\n fsSync.rmSync(join(sourceDirectory, file), { recursive: true });\n }\n })\n );\n });\n};\n\nexport const writeResource = async (\n catalogDir: string,\n resource: Resource,\n options: { path?: string; type: string; override?: boolean; versionExistingContent?: boolean; format?: 'md' | 'mdx' } = {\n path: '',\n type: '',\n override: false,\n versionExistingContent: false,\n format: 'mdx',\n }\n) => {\n const path = options.path || `/${resource.id}`;\n const fullPath = join(catalogDir, path);\n const format = options.format || 'mdx';\n\n // Create directory if it doesn't exist\n fsSync.mkdirSync(fullPath, { recursive: true });\n\n // Create or get lock file path\n const lockPath = join(fullPath, `index.${format}`);\n\n // Ensure the file exists before attempting to lock it\n if (!fsSync.existsSync(lockPath)) {\n fsSync.writeFileSync(lockPath, '');\n }\n\n try {\n // Acquire lock with retry\n await lock(lockPath, {\n retries: 5,\n stale: 10000, // 10 seconds\n });\n\n const exists = await versionExists(catalogDir, resource.id, resource.version);\n\n if (exists && !options.override) {\n throw new Error(`Failed to write ${resource.id} (${options.type}) as the version ${resource.version} already exists`);\n }\n\n const { markdown, ...frontmatter } = resource;\n\n if (options.versionExistingContent && !exists) {\n const currentResource = await getResource(catalogDir, resource.id);\n\n if (currentResource) {\n if (satisfies(resource.version, `>${currentResource.version}`)) {\n await versionResource(catalogDir, resource.id);\n } else {\n throw new Error(`New version ${resource.version} is not greater than current version ${currentResource.version}`);\n }\n }\n }\n\n const document = matter.stringify(markdown.trim(), frontmatter);\n fsSync.writeFileSync(lockPath, document);\n } finally {\n // Always release the lock\n await unlock(lockPath).catch(() => {});\n }\n};\n\nexport const getResource = async (\n catalogDir: string,\n id?: string,\n version?: string,\n options?: { type: string; attachSchema?: boolean },\n filePath?: string\n): Promise<Resource | undefined> => {\n const attachSchema = options?.attachSchema || false;\n const file = filePath || (id ? await findFileById(catalogDir, id, version) : undefined);\n if (!file || !fsSync.existsSync(file)) return;\n\n const { data, content } = matter.read(file);\n\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResourcePath = async (catalogDir: string, id: string, version?: string) => {\n const file = await findFileById(catalogDir, id, version);\n if (!file) return;\n\n return {\n fullPath: file,\n relativePath: file.replace(catalogDir, ''),\n directory: dirname(file.replace(catalogDir, '')),\n };\n};\n\nexport const toResource = async (catalogDir: string, file: string) => {\n const { data, content } = matter.read(file);\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n};\n\nexport const getResources = async (\n catalogDir: string,\n {\n type,\n latestOnly = false,\n ignore = [],\n pattern = '',\n attachSchema = false,\n }: { type: string; pattern?: string; latestOnly?: boolean; ignore?: string[]; attachSchema?: boolean }\n): Promise<Resource[] | undefined> => {\n const ignoreList = latestOnly ? `**/versioned/**` : '';\n const filePattern = pattern || `${catalogDir}/**/${type}/**/index.{md,mdx}`;\n const files = await getFiles(filePattern, [ignoreList, ...ignore]);\n\n if (files.length === 0) return;\n\n return files.map((file) => {\n const { data, content } = matter.read(file);\n\n // Attach the schema if the attachSchema option is set to true\n if (attachSchema && data?.schemaPath) {\n const resourceDirectory = dirname(file);\n const pathToSchema = join(resourceDirectory, data.schemaPath);\n if (fsSync.existsSync(pathToSchema)) {\n const schema = fsSync.readFileSync(pathToSchema, 'utf8');\n // Try to parse the schema\n try {\n data.schema = JSON.parse(schema);\n } catch (error) {\n data.schema = schema;\n }\n }\n }\n return {\n ...data,\n markdown: content.trim(),\n } as Resource;\n });\n};\n\nexport const rmResourceById = async (\n catalogDir: string,\n id: string,\n version?: string,\n options?: { type: string; persistFiles?: boolean }\n) => {\n const files = await getFiles(`${catalogDir}/**/index.{md,mdx}`);\n\n const matchedFiles = await searchFilesForId(files, id, version);\n\n if (matchedFiles.length === 0) {\n throw new Error(`No ${options?.type || 'resource'} found with id: ${id}`);\n }\n\n if (options?.persistFiles) {\n await Promise.all(\n matchedFiles.map(async (file) => {\n await fs.rm(file, { recursive: true });\n })\n );\n } else {\n await Promise.all(\n matchedFiles.map(async (file) => {\n const directory = dirname(file);\n await fs.rm(directory, { recursive: true, force: true });\n })\n );\n }\n};\n\nexport const addFileToResource = async (\n catalogDir: string,\n id: string,\n file: { content: string; fileName: string },\n version?: string\n) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory to write file to');\n\n let fileContent = file.content.trim();\n\n try {\n const json = JSON.parse(fileContent);\n fileContent = JSON.stringify(json, null, 2);\n } catch (error) {\n // Just silently fail if the file is not valid JSON\n // Write it as it is\n }\n\n fsSync.writeFileSync(join(dirname(pathToResource), file.fileName), fileContent);\n};\n\nexport const getFileFromResource = async (catalogDir: string, id: string, file: { fileName: string }, version?: string) => {\n const pathToResource = await findFileById(catalogDir, id, version);\n\n if (!pathToResource) throw new Error('Cannot find directory of resource');\n\n const exists = await fs\n .access(join(dirname(pathToResource), file.fileName))\n .then(() => true)\n .catch(() => false);\n if (!exists) throw new Error(`File ${file.fileName} does not exist in resource ${id} v(${version})`);\n\n return fsSync.readFileSync(join(dirname(pathToResource), file.fileName), 'utf-8');\n};\nexport const getVersionedDirectory = (sourceDirectory: string, version: any): string => {\n return join(sourceDirectory, 'versioned', version);\n};\n\nexport const isLatestVersion = async (catalogDir: string, id: string, version?: string) => {\n const resource = await getResource(catalogDir, id, version);\n if (!resource) return false;\n\n const pathToResource = await getResourcePath(catalogDir, id, version);\n\n return !pathToResource?.relativePath.replace(/\\\\/g, '/').includes('/versioned/');\n};\n"],"mappings":"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","names":["fs","join","match","dirname","join","matter","fsSync","satisfies","dirname","file","join","matter","dirname","join","fsSync","join","join","fs"]}
package/dist/index.d.mts CHANGED
@@ -23,14 +23,7 @@ declare const _default: (path: string) => {
23
23
  * @returns Event[]|Undefined
24
24
  */
25
25
  getEvents: (options?: {
26
- latestOnly
27
- /**
28
- * Init the SDK for EventCatalog
29
- *
30
- * @param path - The path to the EventCatalog directory
31
- *
32
- */
33
- ?: boolean;
26
+ latestOnly?: boolean;
34
27
  attachSchema?: boolean;
35
28
  }) => Promise<Event[]>;
36
29
  /**
@@ -60,7 +53,19 @@ declare const _default: (path: string) => {
60
53
  }, options?: {
61
54
  path?: string;
62
55
  format?: "md" | "mdx";
63
- override?: boolean;
56
+ override
57
+ /**
58
+ * Returns a command from EventCatalog
59
+ * @param id - The id of the command to retrieve
60
+ * @param version - Optional id of the version to get (supports semver)
61
+ * @returns Command|Undefined
62
+ */
63
+ ? /**
64
+ * Returns a command from EventCatalog
65
+ * @param id - The id of the command to retrieve
66
+ * @param version - Optional id of the version to get (supports semver)
67
+ * @returns Command|Undefined
68
+ */: boolean;
64
69
  }) => Promise<void>;
65
70
  /**
66
71
  * Remove an event to EventCatalog (modeled on the standard POSIX rm utility)
@@ -242,14 +247,7 @@ declare const _default: (path: string) => {
242
247
  */
243
248
  writeQuery: (query: Query, options?: {
244
249
  path?: string;
245
- override? /**
246
- * Adds an event to a service in EventCatalog
247
- *
248
- * @param event - The event to write to the service
249
- * @param service - The service and it's id to write to the event to
250
- * @param options - Optional options to write the event
251
- *
252
- */: boolean;
250
+ override?: boolean;
253
251
  versionExistingContent?: boolean;
254
252
  format?: "md" | "mdx";
255
253
  }) => Promise<void>;
@@ -263,18 +261,7 @@ declare const _default: (path: string) => {
263
261
  */
264
262
  writeQueryToService: (query: Query, service: {
265
263
  id: string;
266
- version
267
- /**
268
- * Returns a command from EventCatalog
269
- * @param id - The id of the command to retrieve
270
- * @param version - Optional id of the version to get (supports semver)
271
- * @returns Command|Undefined
272
- */
273
- ? /**
274
- * ================================
275
- * Commands
276
- * ================================
277
- */: string;
264
+ version?: string;
278
265
  }, options?: {
279
266
  path?: string;
280
267
  format?: "md" | "mdx";
@@ -505,6 +492,12 @@ declare const _default: (path: string) => {
505
492
  * @returns Service|Undefined
506
493
  */
507
494
  getService: (id: string, version?: string) => Promise<Service>;
495
+ /**
496
+ * Returns a service from EventCatalog by it's path.
497
+ * @param path - The path to the service to retrieve
498
+ * @returns Service|Undefined
499
+ */
500
+ getServiceByPath: (path: string) => Promise<Service>;
508
501
  /**
509
502
  * Returns all services from EventCatalog
510
503
  * @param latestOnly - optional boolean, set to true to get only latest versions
@@ -626,6 +619,29 @@ declare const _default: (path: string) => {
626
619
  id: string;
627
620
  version: string;
628
621
  }, version?: string) => Promise<void>;
622
+ /**
623
+ * Check to see if a service exists by it's path.
624
+ *
625
+ * @example
626
+ * ```ts
627
+ * import utils from '@eventcatalog/utils';
628
+ *
629
+ * const { isService } = utils('/path/to/eventcatalog');
630
+ *
631
+ * // returns true if the path is a service
632
+ * await isService('/services/InventoryService/index.mdx');
633
+ * ```
634
+ *
635
+ * @param path - The path to the service to check
636
+ * @returns boolean
637
+ */
638
+ isService: (path: string) => Promise<boolean>;
639
+ /**
640
+ * Converts a file to a service.
641
+ * @param file - The file to convert to a service.
642
+ * @returns The service.
643
+ */
644
+ toService: (file: string) => Promise<Service>;
629
645
  /**
630
646
  * ================================
631
647
  * Domains
@@ -780,7 +796,14 @@ declare const _default: (path: string) => {
780
796
  *
781
797
  */
782
798
  writeUser: (user: User, options?: {
783
- override?: boolean;
799
+ override? /**
800
+ * Adds an event to a service in EventCatalog
801
+ *
802
+ * @param event - The event to write to the service
803
+ * @param service - The service and it's id to write to the event to
804
+ * @param options - Optional options to write the event
805
+ *
806
+ */: boolean;
784
807
  }) => Promise<void>;
785
808
  /**
786
809
  * Returns a user from EventCatalog
@@ -889,6 +912,13 @@ declare const _default: (path: string) => {
889
912
  producers: Service[];
890
913
  consumers: Service[];
891
914
  }>;
915
+ /**
916
+ * Returns the owners for a given resource (e.g domain, service, event, command, query, etc.)
917
+ * @param id - The id of the resource to get the owners for
918
+ * @param version - Optional version of the resource
919
+ * @returns { owners: User[] }
920
+ */
921
+ getOwnersForResource: (id: string, version?: string) => Promise<Team[]>;
892
922
  };
893
923
 
894
924
  export { Channel, Command, CustomDoc, Domain, Event, EventCatalog, Message, Query, Service, Team, UbiquitousLanguageDictionary, User, _default as default };