Skip to content

Repository files navigation

🛡 ArchGuard

Contract & Architecture Evolution Manager for NestJS

Automated API diffing, breaking-change detection, and living documentation —
built for teams that move fast without breaking things.

npm versionnpm downloadslicensenodeTypeScripttests


📚 Table of Contents

  1. Why ArchGuard?
  2. Features
  3. Installation
  4. NestJS Setup
  5. Quick Start
  6. Configuration
  7. CLI Commands
  8. Diff Report Example
  9. CI/CD Integration
  10. Programmatic Usage
  11. Roadmap
  12. Contributing
  13. License

💡 Why ArchGuard?

ProblemWithout ArchGuardWith ArchGuard
API contract changesDiscovered by broken FrontendCaught instantly, before merge
Documentation driftSwagger is always outdatedAuto-generated from live spec
Change history"Who changed this route?" 🤷Git-tracked diff reports forever
Breaking changes in PRFound in code review (maybe)Blocked at CI, flagged automatically

✨ Features

  • 🔍 Automatic API Snapshotting — Captures your OpenAPI/Swagger spec at any point in time
  • 🔴 Breaking-Change Detection — Flags removed endpoints, deleted required fields, changed parameter types
  • 🟡 Non-Breaking Change Tracking — Tracks added endpoints, optional parameters, response expansions
  • 📄 Markdown Diff Reports — Beautiful, readable reports committed directly into your git history
  • 📚 Living Architecture Index — Auto-maintained INDEX.md with every diff ever generated
  • 🤝 NestJS-First — Designed for the NestJS + @nestjs/swagger ecosystem; works with any OpenAPI 3.x spec
  • 🤖 GitHub Actions Integration — Posts diff reports as PR comments, blocks merges on breaking changes
  • 🔗 Git Auto-Commit — Optionally auto-commits snapshots and reports so your architecture history is always versioned
  • 📦 Library Mode — Use ArchGuard programmatically in your own scripts or tooling

📦 Installation

As a dev dependency in your NestJS project (recommended)

npm install --save-dev archguard-cli

Then add scripts to your package.json:

{
"scripts": {
"arch:init": "archguard init",
"arch:snapshot": "archguard snapshot",
"arch:diff": "archguard diff",
"arch:history": "archguard history"
}
}

Global install (use anywhere)

npm install -g archguard-cli

Without installing (npx)

npx archguard-cli init
npx archguard-cli snapshot
npx archguard-cli diff

🏗 NestJS Setup

ArchGuard reads your live OpenAPI spec. Make sure Swagger is enabled in your NestJS app:

// src/main.tsimport{NestFactory}from'@nestjs/core';import{DocumentBuilder,SwaggerModule}from'@nestjs/swagger';import{AppModule}from'./app.module';asyncfunctionbootstrap(){constapp=awaitNestFactory.create(AppModule);constconfig=newDocumentBuilder().setTitle('My API').setVersion('1.0').build();constdocument=SwaggerModule.createDocument(app,config);SwaggerModule.setup('api',app,document);// ↑ This exposes the JSON spec at: http://localhost:3000/api-jsonawaitapp.listen(3000);}bootstrap();

ArchGuard fetches http://localhost:3000/api-json by default.
You can override this in archguard.config.json or via --url.


🚀 Quick Start

# 1. Initialize ArchGuard in your NestJS project
npx archguard-cli init
# 2. Start your NestJS app
npm run start:dev
# 3. Capture the current API as a baseline snapshot
npx archguard-cli snapshot
# 4. Make changes to your API (add a route, change a DTO, remove a param...)# 5. Generate a diff report
npx archguard-cli diff

Expected output for archguard diff:

🛡 ArchGuard Diff
✔ Current snapshot captured
✔ Analysis complete — 3 change(s) detected
────────────────────────────────────────────────────────────
📊 Changes: 3 | 🔴 Breaking: 1
➕ Added: 1 endpoints | ➖ Removed: 1 | 🔄 Modified: 1
📐 Schemas: +0 ~1 -0
────────────────────────────────────────────────────────────
✔ Report saved: ./docs/architecture/history/diff-2024-01-15T10-30-00-to-2024-01-15T14-45-00.md
✔ Diff completed! Check the report for details.

The generated report appears at ./docs/architecture/history/diff-latest.md — ready to commit and share with your Frontend team.


⚙️ Configuration

ArchGuard is configured via archguard.config.json in your project root (created automatically by archguard init).

{
"projectName": "payments-api",
"historyPath": "./docs/architecture/history",
"snapshotPath": "./.archguard",
"swaggerUrl": "http://localhost:3000/api-json",
"notify": {
"breakingChangesOnly": false
},
"git": {
"autoCommit": true,
"commitMessage": "chore(docs): update architecture history [skip ci]"
}
}
OptionTypeDefaultDescription
projectNamestringfolder nameDisplay name for your project
historyPathstring"./docs/architecture/history"Where diff reports are stored
snapshotPathstring"./.archguard"Where snapshots are stored
swaggerUrlstring"http://localhost:3000/api-json"URL to fetch the OpenAPI JSON spec
notify.breakingChangesOnlybooleanfalseOnly flag breaking changes
git.autoCommitbooleanfalseAuto-commit snapshots and reports
git.commitMessagestring"chore(docs): ..."Commit message template

💻 CLI Commands

CommandDescriptionOptions
archguard initInitialize ArchGuard in the current directory--force overwrite existing config
archguard snapshotCapture the current OpenAPI spec--url <url> override Swagger URL
archguard diffCompare latest snapshot with current spec--url <url>, --no-commit
archguard historyList stored snapshots and diff reports--snapshots, --reports

archguard init

Creates:

  • archguard.config.json — project configuration
  • .archguard/ — snapshot storage (add to .gitignore if desired)
  • docs/architecture/history/ — diff report history (commit this!)
  • Appends ArchGuard entries to .gitignore

archguard snapshot

archguard snapshot [--url http://localhost:3000/api-json]

Fetches your OpenAPI spec and saves a timestamped JSON snapshot. Always writes snapshot-latest.json as the baseline for the next diff.

archguard diff

archguard diff [--url <url>] [--no-commit]
  1. Loads snapshot-latest.json as baseline
  2. Fetches the current spec from your running app
  3. Runs the diff engine (endpoints + schemas + parameters + responses)
  4. Classifies each change as breaking, non-breaking, or informational
  5. Generates a Markdown report with Before/After details
  6. Updates INDEX.md and optionally auto-commits to git

archguard history

archguard history [--snapshots] [--reports]

Lists all snapshots and diff reports with timestamps.


📋 Diff Report Example

Generated reports look like this:

# 🛡 ArchGuard Diff Report**Project:** payments-api **From:**`snapshot-2024-01-14T10-00-00.json`**To:**`snapshot-2024-01-15T14-30-00.json`## 📊 Summary| Metric | Count ||--------|-------|| 🔴 Breaking Changes |**2**|| Total Changes | 5 || ➕ Added Endpoints | 1 || ➖ Removed Endpoints | 1 || 🔄 Modified Endpoints | 0 || Modified Schemas | 2 |> ⚠️ **WARNING:** 2 breaking change(s) require immediate Frontend attention.## 🔌 Endpoint Changes### ➖ 🔴 `DELETE /v1/users/{id}`**Severity:** BREAKING **Change:**[Users] Endpoint removed: Delete user **Frontend Impact:** ⚠️ Remove all calls to this endpoint from your codebase.
---### ➕ 🟢 `POST /v2/users/{id}/deactivate`**Severity:** NON-BREAKING **Change:**[Users] Endpoint added: Deactivate user **Frontend Impact:** New endpoint available — implement integration if needed.

🤖 CI/CD Integration

GitHub Actions

Copy .github/workflows/archguard.yml to your NestJS repository:

name: 🛡 ArchGuard API Contract Checkon:
push:
branches: [main]pull_request:
branches: [main]jobs:
api-contract-check:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4with:
node-version: '20'cache: 'npm'
- name: Install dependenciesrun: npm ci
- name: Start NestJS apprun: | npm run start:prod & timeout 60 bash -c 'until curl -sf http://localhost:3000/api-json; do sleep 2; done' - name: Restore snapshot cacheuses: actions/cache@v4with:
path: .archguard/key: archguard-snapshot-${{ github.base_ref || github.ref_name }}
- name: Run ArchGuard diffif: github.event_name == 'pull_request'run: npx archguard-cli diff --no-commit
- name: Comment PR with diffif: github.event_name == 'pull_request'uses: actions/github-script@v7with:
script: | const fs = require('fs'); const file = 'docs/architecture/history/diff-latest.md'; if (!fs.existsSync(file)) return; const body = fs.readFileSync(file, 'utf-8').slice(0, 65000); await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## 🛡 ArchGuard API Diff\n\n${body}` }); - name: Block merge on breaking changesif: github.event_name == 'pull_request'run: | if grep -q "Breaking Changes | \*\*[1-9]" docs/architecture/history/diff-latest.md 2>/dev/null; then echo "🔴 Breaking API changes detected! Fix before merging." exit 1 fi - name: Save snapshot on main pushif: github.ref == 'refs/heads/main' && github.event_name == 'push'run: npx archguard-cli snapshot

🔧 Programmatic Usage

Use ArchGuard as a library in your own scripts:

import{captureSnapshot,loadLatestSnapshot,saveSnapshot,generateDiff,generateMarkdownReport,saveReport,loadConfig,}from'archguard-cli';constconfig=loadConfig();// reads archguard.config.json// Capture current stateconstcurrent=awaitcaptureSnapshot(config);// Load previous stateconstprevious=loadLatestSnapshot(config);if(previous){// Generate diffconstreport=generateDiff(previous,current);console.log(`Breaking changes: ${report.summary.breakingChanges}`);// Generate and save Markdown reportconstmarkdown=generateMarkdownReport(report,config);saveReport(markdown,report,config);}// Save current as new baselinesaveSnapshot(current,config);

🗺 Roadmap

PhaseFeatureStatus
Phase 1Core CLI — init, snapshot, diff, history✅ Done
Phase 2GitHub Actions CI/CD + PR comments✅ Done
Phase 347 unit tests + Jest coverage✅ Done
Phase 4Static extraction from NestJS decorators (no running server)🔨 In Progress
Phase 5Frontend SDK type generation from diff📋 Planned
Phase 6Web dashboard — visual architecture timeline📋 Planned

🤝 Contributing

Contributions are welcome!

# 1. Fork and clone
git clone https://github.com/YvesDeSa/ArchGuard.git
cd ArchGuard
# 2. Install dependencies
npm install
# 3. Run tests
npm test# 4. Develop with live TypeScript (no build step)
npm run dev -- snapshot --url http://localhost:3000/api-json
# 5. Build
npm run build

Project Structure

src/
├── bin/
│ └── archguard.ts # CLI entry point (Commander.js)
├── commands/
│ ├── init.ts # archguard init
│ ├── snapshot.ts # archguard snapshot
│ ├── diff.ts # archguard diff
│ └── history.ts # archguard history
├── core/
│ ├── snapshot.ts # Snapshot capture & persistence
│ ├── differ.ts # OpenAPI diff engine (breaking change detection)
│ ├── reporter.ts # Markdown report generator
│ └── git-integration.ts # simple-git auto-commit
├── utils/
│ ├── config.ts # Config loader & path resolution
│ └── logger.ts # Chalk-powered logger
├── types/
│ └── index.ts # All TypeScript interfaces
├── __tests__/
│ ├── differ.test.ts # 35 diff engine tests
│ ├── snapshot.test.ts # Snapshot I/O tests
│ └── reporter.test.ts # Report generation tests
└── index.ts # Public library API

📄 License

MIT © Yves De Sá


Made with ❤️ for the NestJS community

NPM · Issues · Changelog

If ArchGuard saved you from a breaking change, give it a ⭐

About

🛡️ Automated API diffing and breaking-change detection for NestJS and Swagger.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages