You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: map Compass DEPENDS_ON relationships to service markdown (Phase 3) (#144)
* feat: map Compass DEPENDS_ON relationships to service markdown (Phase 3)
Parse relationships.DEPENDS_ON from Compass YAML and resolve referenced
services using a two-pass approach. First pass collects all services into
a map (Compass ARN → service ID), second pass resolves dependencies and
generates markdown with linked dependency sections.
- Add ResolvedDependency type to src/types.ts
- Update defaultMarkdown() to render Dependencies section with links
- Update loadService() to accept optional dependencies parameter
- Implement two-pass service processing in index.ts for dependency resolution
- Handle missing dependency targets gracefully (log warning, don't crash)
- Update test fixtures with cross-referencing DEPENDS_ON ARNs
- Add 6 new tests covering relationship resolution scenarios
- Mark Phase 3 as complete in PLAN.md
https://claude.ai/code/session_01Nciw9idSbSrmH2PU7y8J7a
* chore: update pnpm-lock.yaml and add pnpm-workspace.yaml
https://claude.ai/code/session_01Nciw9idSbSrmH2PU7y8J7a
* fix: address PR review - eliminate duplicate YAML parsing and typeFilter logic
- Cache parsed configs in first pass, reuse in second pass instead of
calling loadConfig() twice per service
- Consolidate typeFilter check into first pass only (was duplicated)
- Remove unused `config` field from serviceMap entries
- Remove redundant serviceId re-computation in second pass
https://claude.ai/code/session_01Nciw9idSbSrmH2PU7y8J7a
* fix: remove pnpm v10 artifacts breaking CI with pnpm v8
Remove pnpm-workspace.yaml (pnpm v10 feature) and restore the original
pnpm-lock.yaml from master. CI uses pnpm v8 which doesn't support the
ignoredBuiltDependencies config or the libc metadata added by pnpm v10.
CI's pnpm install will resolve any new dependencies from package.json.
https://claude.ai/code/session_01Nciw9idSbSrmH2PU7y8J7a
* fix: escape HTML special chars in sanitizeMarkdownText to prevent XSS
The sanitizeMarkdownText function only escaped markdown link characters
(brackets and parentheses) but not HTML special characters. In an MDX
context, a malicious dependency name like <script>alert(1)</script>
would be rendered as executable HTML.
Now escapes &, <, >, ", and ' as HTML entities before escaping markdown
syntax, preventing XSS in generated service markdown.
https://claude.ai/code/session_01Nciw9idSbSrmH2PU7y8J7a
* docs: initialise CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: format CLAUDE.md with prettier
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+
## Project Overview
6
+
7
+
An EventCatalog generator plugin that reads Atlassian Compass YAML files and produces service entries in an EventCatalog. It parses `compass.yml` files, extracts metadata (links, badges, owners, dependencies), and uses the `@eventcatalog/sdk` to write services (and optionally domains) into the catalog's file system.
8
+
9
+
## Commands
10
+
11
+
Package manager is pnpm (v8 in CI). All commands use `pnpm run`.
12
+
13
+
```
14
+
pnpm install # install deps
15
+
pnpm run build # build with tsup (CJS + ESM + .d.ts into dist/)
16
+
pnpm run test # run vitest in watch mode
17
+
pnpm run test -- run # single test run (no watch)
18
+
pnpm run lint # eslint
19
+
pnpm run lint:fix # eslint with auto-fix
20
+
pnpm run format:diff # prettier check (CI uses this)
21
+
pnpm run format # prettier write
22
+
```
23
+
24
+
CI runs three checks on PRs: Tests, Lint (eslint + prettier), and Verify Build. All must pass.
25
+
26
+
## Architecture
27
+
28
+
The plugin exports a single async function from `src/index.ts` that EventCatalog calls with a config object and `GeneratorProps` options. Processing happens in two passes over the services array:
29
+
30
+
Pass 1 (`src/index.ts`): Load each compass YAML via `loadConfig` from `src/compass.ts`, apply the optional `typeFilter`, and build a `serviceMap` keyed by Compass ARN so that `DEPENDS_ON` relationships can be resolved between services.
31
+
32
+
Pass 2 (`src/index.ts`): For each processable file, call `loadService` from `src/service.ts` to build the `Service` object (markdown template with links, dependencies, badges, owners, repository URL), then write it via the EventCatalog SDK. If a `domain` option is provided, `src/domain.ts` handles creating/versioning the domain and associating services to it.
33
+
34
+
Key modules:
35
+
36
+
-`src/compass.ts` — `CompassConfig` type definition and YAML loading. The type mirrors the Atlassian Compass config-as-code spec.
37
+
-`src/service.ts` — Transforms a `CompassConfig` into an EventCatalog `Service`. Contains markdown template generation, badge building, URL sanitization (XSS prevention), and link formatting.
38
+
-`src/domain.ts` — `Domain` class that manages domain creation, versioning, and service association via the SDK.
39
+
-`src/validation.ts` — Zod schemas for validating `GeneratorProps` at runtime.
Single test file at `src/test/plugin.test.ts`. Tests run the full plugin against a temporary catalog directory (`src/test/catalog/`) that gets cleaned up in `afterEach`. Test fixture YAML files live in `src/test/`. The `vitest.setup.ts` adds a custom `toMatchMarkdown` matcher that normalizes whitespace.
45
+
46
+
The `@eventcatalog/sdk` is inlined during testing (configured in `vitest.config.ts` via `server.deps.inline`).
47
+
48
+
## Security Considerations
49
+
50
+
`src/service.ts` sanitizes all user-controlled text before embedding in markdown/MDX: `sanitizeMarkdownText` escapes HTML special characters and markdown link syntax; `sanitizeUrl` only allows `http:`/`https:` protocols. `src/index.ts` sanitizes service IDs via `sanitizeId` to prevent path traversal.
**Important**: The SDK does **not** have a generic `addRelationshipToService()` function. The SDK models relationships through specific mechanisms:
200
-
201
-
- `sends`/ `receives` — for message flows (events, commands, queries between services via channels)
202
-
- `writesTo`/ `readsFrom` — for data store relationships
203
-
- `<NodeGraph />`— renders the service/domain graph visually in markdown
204
-
205
-
Compass `DEPENDS_ON` is a general architectural dependency, not a message flow. It doesn't map cleanly to `sends`/`receives` (which are for events/commands, not service-to-service dependencies). Using `addEventToService()` would be incorrect here — that function is for linking events to services, not for expressing that one service depends on another.
206
-
207
-
**Approach**: Express dependencies through the service markdown and the domain's `<NodeGraph />`. The `<NodeGraph />` component already renders all services within a domain and their connections. We enrich each service's markdown with an explicit "Dependencies" section listing what it depends on, and ensure both services are in the same domain so the graph visualizes the relationship.
193
+
- Added `ResolvedDependency` type (`{ id: string; name: string }`) to `src/types.ts`
194
+
- Updated `defaultMarkdown()` in `src/service.ts` to accept and render a `dependencies` parameter, generating a "Dependencies" section with links to dependent services (or "No known dependencies." when none exist)
195
+
- Updated `loadService()` to accept optional `dependencies` parameter and pass it through to markdown generation
196
+
- Implemented two-pass approach in `src/index.ts`:
197
+
1.**First pass**: Collects all services being processed into a Map (Compass ARN → service ID + name), respecting `typeFilter`
198
+
2.**Second pass**: For each service, resolves `DEPENDS_ON` ARNs against the map, logs warnings for unresolvable dependencies, and writes services with resolved dependency markdown
199
+
- Missing dependency targets are handled gracefully (warning logged, not crashed)
200
+
- Dependency text in markdown is sanitized against injection
208
201
209
-
1. Collect all service IDs being processed in a Map (Compass ARN → EventCatalog ID)
210
-
2. For each service, resolve its `DEPENDS_ON` ARNs to EventCatalog service IDs
211
-
3. Include the dependency list in the service's generated markdown
212
-
4. If both services are in the same domain, the `<NodeGraph />` will show them together
202
+
### 3.2 — Tests for Phase 3 ✅
213
203
214
-
**File**: `src/service.ts`
215
-
216
-
Add a dependencies section to the generated markdown:
0 commit comments