cerber-core 1.0.4 → 1.1.0

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 (37) hide show
  1. package/CHANGELOG.md +158 -68
  2. package/README.md +75 -0
  3. package/USAGE_GUIDE.md +254 -0
  4. package/bin/cerber +121 -105
  5. package/dev/templates/cerber-guardian.mjs.tpl +44 -0
  6. package/dev/templates/cerber.yml.tpl +53 -0
  7. package/dev/templates/health-checks.ts.tpl +11 -0
  8. package/dev/templates/health-route.ts.tpl +50 -0
  9. package/dev/templates/pre-commit.tpl +4 -0
  10. package/dist/cli/contract-parser.d.ts +13 -0
  11. package/dist/cli/contract-parser.d.ts.map +1 -0
  12. package/dist/cli/contract-parser.js +241 -0
  13. package/dist/cli/contract-parser.js.map +1 -0
  14. package/dist/cli/init.d.ts +11 -0
  15. package/dist/cli/init.d.ts.map +1 -0
  16. package/dist/cli/init.js +241 -0
  17. package/dist/cli/init.js.map +1 -0
  18. package/dist/cli/template-generator.d.ts +28 -0
  19. package/dist/cli/template-generator.d.ts.map +1 -0
  20. package/dist/cli/template-generator.js +227 -0
  21. package/dist/cli/template-generator.js.map +1 -0
  22. package/dist/cli/types.d.ts +70 -0
  23. package/dist/cli/types.d.ts.map +1 -0
  24. package/dist/cli/types.js +8 -0
  25. package/dist/cli/types.js.map +1 -0
  26. package/package.json +106 -104
  27. package/solo/templates/cerber-guardian.mjs.tpl +44 -0
  28. package/solo/templates/cerber.yml.tpl +53 -0
  29. package/solo/templates/health-checks.ts.tpl +29 -0
  30. package/solo/templates/health-route.ts.tpl +50 -0
  31. package/solo/templates/pre-commit.tpl +4 -0
  32. package/team/templates/CODEOWNERS.tpl +6 -0
  33. package/team/templates/cerber-guardian.mjs.tpl +44 -0
  34. package/team/templates/cerber.yml.tpl +53 -0
  35. package/team/templates/health-checks.ts.tpl +10 -0
  36. package/team/templates/health-route.ts.tpl +50 -0
  37. package/team/templates/pre-commit.tpl +4 -0
package/package.json CHANGED
@@ -1,104 +1,106 @@
1
- {
2
- "name": "cerber-core",
3
- "version": "1.0.4",
4
- "description": "Your architecture roadmap becomes executable law. Guardian blocks commits that violate your plan. Pay architect once, Cerber enforces forever. Save $6k/month/dev.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "type": "module",
8
- "bin": {
9
- "cerber": "./bin/cerber",
10
- "cerber-guardian": "./bin/cerber-guardian",
11
- "cerber-health": "./bin/cerber-health",
12
- "cerber-focus": "./bin/cerber-focus",
13
- "cerber-morning": "./bin/cerber-morning",
14
- "cerber-repair": "./bin/cerber-repair"
15
- },
16
- "exports": {
17
- ".": "./dist/index.js",
18
- "./guardian": "./dist/guardian/index.js",
19
- "./cerber": "./dist/cerber/index.js",
20
- "./types": "./dist/types.js"
21
- },
22
- "scripts": {
23
- "build": "tsc",
24
- "test": "jest",
25
- "lint": "eslint src/**/*.ts",
26
- "format": "prettier --write \"src/**/*.ts\"",
27
- "prepublishOnly": "npm run build",
28
- "validate": "node bin/cerber-guardian",
29
- "health-check": "node bin/cerber-health",
30
- "morning": "node solo/scripts/cerber-daily-check.js",
31
- "repair": "node solo/scripts/cerber-auto-repair.js",
32
- "repair:dry": "node solo/scripts/cerber-auto-repair.js --dry-run",
33
- "dashboard": "node solo/scripts/cerber-dashboard.js"
34
- },
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/Agaslez/cerber-core.git"
38
- },
39
- "keywords": [
40
- "pre-commit",
41
- "code-quality",
42
- "architecture",
43
- "validation",
44
- "health-check",
45
- "monitoring",
46
- "cerber",
47
- "guardian",
48
- "typescript",
49
- "ci-cd",
50
- "automation",
51
- "team-collaboration",
52
- "solo-developer",
53
- "focus-mode",
54
- "module-system"
55
- ],
56
- "author": {
57
- "name": "Agata Sleziak",
58
- "email": "agata@example.com",
59
- "url": "https://github.com/Agaslez"
60
- },
61
- "contributors": [
62
- {
63
- "name": "Stefan Pitek",
64
- "role": "Collaborator"
65
- }
66
- ],
67
- "license": "MIT",
68
- "bugs": {
69
- "url": "https://github.com/Agaslez/cerber-core/issues"
70
- },
71
- "homepage": "https://github.com/Agaslez/cerber-core#readme",
72
- "peerDependencies": {
73
- "typescript": ">=5.0.0"
74
- },
75
- "dependencies": {
76
- "chalk": "^5.3.0",
77
- "commander": "^12.0.0"
78
- },
79
- "devDependencies": {
80
- "@types/jest": "^29.5.0",
81
- "@types/node": "^20.0.0",
82
- "@typescript-eslint/eslint-plugin": "^6.0.0",
83
- "@typescript-eslint/parser": "^6.0.0",
84
- "eslint": "^8.50.0",
85
- "jest": "^29.7.0",
86
- "prettier": "^3.0.0",
87
- "ts-jest": "^29.1.0",
88
- "typescript": "^5.3.0"
89
- },
90
- "engines": {
91
- "node": ">=16.0.0"
92
- },
93
- "files": [
94
- "dist",
95
- "bin",
96
- "solo",
97
- "team",
98
- "examples",
99
- ".cerber-example",
100
- "LICENSE",
101
- "README.md",
102
- "CHANGELOG.md"
103
- ]
104
- }
1
+ {
2
+ "name": "cerber-core",
3
+ "version": "1.1.0",
4
+ "description": "Your architecture roadmap becomes executable law. Guardian blocks commits that violate your plan. Pay architect once, Cerber enforces forever. Save $6k/month/dev.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "cerber": "./bin/cerber",
10
+ "cerber-guardian": "./bin/cerber-guardian",
11
+ "cerber-health": "./bin/cerber-health",
12
+ "cerber-focus": "./bin/cerber-focus",
13
+ "cerber-morning": "./bin/cerber-morning",
14
+ "cerber-repair": "./bin/cerber-repair"
15
+ },
16
+ "exports": {
17
+ ".": "./dist/index.js",
18
+ "./guardian": "./dist/guardian/index.js",
19
+ "./cerber": "./dist/cerber/index.js",
20
+ "./types": "./dist/types.js"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "test": "jest",
25
+ "lint": "eslint src/**/*.ts",
26
+ "format": "prettier --write \"src/**/*.ts\"",
27
+ "prepublishOnly": "npm run build",
28
+ "validate": "node bin/cerber-guardian",
29
+ "health-check": "node bin/cerber-health",
30
+ "morning": "node solo/scripts/cerber-daily-check.js",
31
+ "repair": "node solo/scripts/cerber-auto-repair.js",
32
+ "repair:dry": "node solo/scripts/cerber-auto-repair.js --dry-run",
33
+ "dashboard": "node solo/scripts/cerber-dashboard.js"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/Agaslez/cerber-core.git"
38
+ },
39
+ "keywords": [
40
+ "pre-commit",
41
+ "code-quality",
42
+ "architecture",
43
+ "validation",
44
+ "health-check",
45
+ "monitoring",
46
+ "cerber",
47
+ "guardian",
48
+ "typescript",
49
+ "ci-cd",
50
+ "automation",
51
+ "team-collaboration",
52
+ "solo-developer",
53
+ "focus-mode",
54
+ "module-system"
55
+ ],
56
+ "author": {
57
+ "name": "Agata Sleziak",
58
+ "email": "agata@example.com",
59
+ "url": "https://github.com/Agaslez"
60
+ },
61
+ "contributors": [
62
+ {
63
+ "name": "Stefan Pitek",
64
+ "role": "Collaborator"
65
+ }
66
+ ],
67
+ "license": "MIT",
68
+ "bugs": {
69
+ "url": "https://github.com/Agaslez/cerber-core/issues"
70
+ },
71
+ "homepage": "https://github.com/Agaslez/cerber-core#readme",
72
+ "peerDependencies": {
73
+ "typescript": ">=5.0.0"
74
+ },
75
+ "dependencies": {
76
+ "chalk": "^5.3.0",
77
+ "commander": "^12.0.0"
78
+ },
79
+ "devDependencies": {
80
+ "@types/jest": "^29.5.0",
81
+ "@types/node": "^20.0.0",
82
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
83
+ "@typescript-eslint/parser": "^6.0.0",
84
+ "eslint": "^8.50.0",
85
+ "jest": "^29.7.0",
86
+ "prettier": "^3.0.0",
87
+ "ts-jest": "^29.1.0",
88
+ "typescript": "^5.3.0"
89
+ },
90
+ "engines": {
91
+ "node": ">=16.0.0"
92
+ },
93
+ "files": [
94
+ "dist",
95
+ "bin",
96
+ "examples",
97
+ ".cerber-example",
98
+ "solo",
99
+ "dev",
100
+ "team",
101
+ "LICENSE",
102
+ "README.md",
103
+ "CHANGELOG.md",
104
+ "USAGE_GUIDE.md"
105
+ ]
106
+ }
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ // Generated by Cerber init - DO NOT EDIT MANUALLY
3
+ // To regenerate: npx cerber init --force
4
+
5
+ import { execSync } from 'child_process';
6
+ import fs from 'fs';
7
+
8
+ const SCHEMA_FILE = '{{SCHEMA_FILE}}';
9
+ const APPROVALS_TAG = '{{APPROVALS_TAG}}';
10
+
11
+ async function main() {
12
+ console.log('🛡️ Cerber Guardian: Validating staged files...');
13
+
14
+ if (!fs.existsSync(SCHEMA_FILE)) {
15
+ console.error(`❌ Schema file not found: ${SCHEMA_FILE}`);
16
+ console.error('Guardian MVP: schema missing. Add your rules to proceed.');
17
+ process.exit(1);
18
+ }
19
+
20
+ let stagedFiles;
21
+ try {
22
+ stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf-8' })
23
+ .trim()
24
+ .split('\n')
25
+ .filter(Boolean);
26
+ } catch (err) {
27
+ console.error('❌ Failed to get staged files');
28
+ process.exit(1);
29
+ }
30
+
31
+ if (stagedFiles.length === 0) {
32
+ console.log('✅ No files staged for commit');
33
+ return;
34
+ }
35
+
36
+ console.log(`Checking ${stagedFiles.length} file(s)...`);
37
+ console.log('Guardian MVP: schema detected. Add validation rules to enforce imports/forbidden patterns.');
38
+ console.log('✅ All checks passed');
39
+ }
40
+
41
+ main().catch(err => {
42
+ console.error('❌ Guardian check failed:', err?.message || err);
43
+ process.exit(1);
44
+ });
@@ -0,0 +1,53 @@
1
+ # Generated by Cerber init
2
+ name: Cerber CI
3
+
4
+ on:
5
+ push:
6
+ branches: {{CI_BRANCHES}}
7
+ pull_request:
8
+ branches: {{CI_BRANCHES}}
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ cerber-ci:
13
+ name: Cerber CI
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: '20'
24
+ cache: 'npm'
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Build (if script exists)
30
+ run: |
31
+ if npm run | grep -q "build"; then
32
+ npm run build
33
+ else
34
+ echo "No build script defined; skipping"
35
+ fi
36
+
37
+ - name: Test (if script exists)
38
+ run: |
39
+ if npm run | grep -q "test"; then
40
+ npm test
41
+ else
42
+ echo "No test script defined; skipping"
43
+ fi
44
+
45
+ - name: Run Guardian
46
+ run: |
47
+ if npm run | grep -q "cerber:guardian"; then
48
+ npm run cerber:guardian
49
+ else
50
+ node scripts/cerber-guardian.mjs
51
+ fi
52
+
53
+ {{POST_DEPLOY_BLOCK}}
@@ -0,0 +1,29 @@
1
+ // Generated by Cerber init - CUSTOMIZE THIS FILE
2
+ // To regenerate template: npx cerber init --force
3
+
4
+ import { CerberCheck, makeIssue } from 'cerber-core';
5
+
6
+ export const checks: Record<string, CerberCheck> = {
7
+ database: async () => {
8
+ // TODO: Implement your database health check
9
+ // Example:
10
+ // try {
11
+ // await db.query('SELECT 1');
12
+ // return [];
13
+ // } catch (err) {
14
+ // return [
15
+ // makeIssue({
16
+ // code: 'DB_CONNECTION_FAILED',
17
+ // component: 'database',
18
+ // diagnosis: 'Cannot connect to database',
19
+ // rootCause: 'Database server is down or unreachable',
20
+ // fix: 'Check DATABASE_URL and verify DB is running',
21
+ // severity: 'critical',
22
+ // durationMs: 0
23
+ // })
24
+ // ];
25
+ // }
26
+
27
+ return []; // Placeholder - implement your check
28
+ },
29
+ };
@@ -0,0 +1,50 @@
1
+ // Generated by Cerber init - CUSTOMIZE THIS FILE
2
+
3
+ import { checks } from './health-checks.js';
4
+
5
+ export async function healthHandler(req: any, res: any) {
6
+ const startTime = Date.now();
7
+
8
+ try {
9
+ const results = await Promise.all(
10
+ Object.entries(checks).map(async ([name, check]) => ({
11
+ name,
12
+ issues: await check()
13
+ }))
14
+ );
15
+
16
+ const allIssues = results.flatMap(r => r.issues);
17
+ const critical = allIssues.filter(i => i.severity === 'critical').length;
18
+ const errors = allIssues.filter(i => i.severity === 'error').length;
19
+ const warnings = allIssues.filter(i => i.severity === 'warning').length;
20
+
21
+ const status = critical > 0 ? 'unhealthy' :
22
+ errors > 0 ? 'degraded' : 'healthy';
23
+
24
+ const statusCode = status === 'healthy' ? 200 : 503;
25
+
26
+ res.status(statusCode).json({
27
+ status,
28
+ timestamp: new Date().toISOString(),
29
+ durationMs: Date.now() - startTime,
30
+ summary: {
31
+ totalChecks: results.length,
32
+ failedChecks: results.filter(r => r.issues.length > 0).length,
33
+ criticalIssues: critical,
34
+ errorIssues: errors,
35
+ warningIssues: warnings
36
+ },
37
+ components: allIssues
38
+ });
39
+ } catch (err: any) {
40
+ res.status(503).json({
41
+ status: 'error',
42
+ message: 'Health check failed',
43
+ error: err.message
44
+ });
45
+ }
46
+ }
47
+
48
+ // Usage in your server:
49
+ // import { healthHandler } from './cerber/health-route.js';
50
+ // app.get('{{HEALTH_ENDPOINT}}', healthHandler);
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Generated by Cerber init
3
+
4
+ npm run cerber:guardian
@@ -0,0 +1,6 @@
1
+ # Generated by Cerber init
2
+
3
+ /CERBER.md {{OWNERS}}
4
+ /{{SCHEMA_FILE}} {{OWNERS}}
5
+ /.github/workflows/cerber.yml {{OWNERS}}
6
+ /scripts/cerber-guardian.mjs {{OWNERS}}
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ // Generated by Cerber init - DO NOT EDIT MANUALLY
3
+ // To regenerate: npx cerber init --force
4
+
5
+ import { execSync } from 'child_process';
6
+ import fs from 'fs';
7
+
8
+ const SCHEMA_FILE = '{{SCHEMA_FILE}}';
9
+ const APPROVALS_TAG = '{{APPROVALS_TAG}}';
10
+
11
+ async function main() {
12
+ console.log('🛡️ Cerber Guardian: Validating staged files...');
13
+
14
+ if (!fs.existsSync(SCHEMA_FILE)) {
15
+ console.error(`❌ Schema file not found: ${SCHEMA_FILE}`);
16
+ console.error('Guardian MVP: schema missing. Add your rules to proceed.');
17
+ process.exit(1);
18
+ }
19
+
20
+ let stagedFiles;
21
+ try {
22
+ stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf-8' })
23
+ .trim()
24
+ .split('\n')
25
+ .filter(Boolean);
26
+ } catch (err) {
27
+ console.error('❌ Failed to get staged files');
28
+ process.exit(1);
29
+ }
30
+
31
+ if (stagedFiles.length === 0) {
32
+ console.log('✅ No files staged for commit');
33
+ return;
34
+ }
35
+
36
+ console.log(`Checking ${stagedFiles.length} file(s)...`);
37
+ console.log('Guardian MVP: schema detected. Add validation rules to enforce imports/forbidden patterns.');
38
+ console.log('✅ All checks passed');
39
+ }
40
+
41
+ main().catch(err => {
42
+ console.error('❌ Guardian check failed:', err?.message || err);
43
+ process.exit(1);
44
+ });
@@ -0,0 +1,53 @@
1
+ # Generated by Cerber init
2
+ name: Cerber CI
3
+
4
+ on:
5
+ push:
6
+ branches: {{CI_BRANCHES}}
7
+ pull_request:
8
+ branches: {{CI_BRANCHES}}
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ cerber-ci:
13
+ name: Cerber CI
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: '20'
24
+ cache: 'npm'
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Build (if script exists)
30
+ run: |
31
+ if npm run | grep -q "build"; then
32
+ npm run build
33
+ else
34
+ echo "No build script defined; skipping"
35
+ fi
36
+
37
+ - name: Test (if script exists)
38
+ run: |
39
+ if npm run | grep -q "test"; then
40
+ npm test
41
+ else
42
+ echo "No test script defined; skipping"
43
+ fi
44
+
45
+ - name: Run Guardian
46
+ run: |
47
+ if npm run | grep -q "cerber:guardian"; then
48
+ npm run cerber:guardian
49
+ else
50
+ node scripts/cerber-guardian.mjs
51
+ fi
52
+
53
+ {{POST_DEPLOY_BLOCK}}
@@ -0,0 +1,10 @@
1
+ // Generated by Cerber init - CUSTOMIZE THIS FILE
2
+ // To regenerate template: npx cerber init --force
3
+
4
+ import { CerberCheck, makeIssue } from 'cerber-core';
5
+
6
+ export const checks: Record<string, CerberCheck> = {
7
+ database: async () => {
8
+ return [];
9
+ },
10
+ };
@@ -0,0 +1,50 @@
1
+ // Generated by Cerber init - CUSTOMIZE THIS FILE
2
+
3
+ import { checks } from './health-checks.js';
4
+
5
+ export async function healthHandler(req: any, res: any) {
6
+ const startTime = Date.now();
7
+
8
+ try {
9
+ const results = await Promise.all(
10
+ Object.entries(checks).map(async ([name, check]) => ({
11
+ name,
12
+ issues: await check()
13
+ }))
14
+ );
15
+
16
+ const allIssues = results.flatMap(r => r.issues);
17
+ const critical = allIssues.filter(i => i.severity === 'critical').length;
18
+ const errors = allIssues.filter(i => i.severity === 'error').length;
19
+ const warnings = allIssues.filter(i => i.severity === 'warning').length;
20
+
21
+ const status = critical > 0 ? 'unhealthy' :
22
+ errors > 0 ? 'degraded' : 'healthy';
23
+
24
+ const statusCode = status === 'healthy' ? 200 : 503;
25
+
26
+ res.status(statusCode).json({
27
+ status,
28
+ timestamp: new Date().toISOString(),
29
+ durationMs: Date.now() - startTime,
30
+ summary: {
31
+ totalChecks: results.length,
32
+ failedChecks: results.filter(r => r.issues.length > 0).length,
33
+ criticalIssues: critical,
34
+ errorIssues: errors,
35
+ warningIssues: warnings
36
+ },
37
+ components: allIssues
38
+ });
39
+ } catch (err: any) {
40
+ res.status(503).json({
41
+ status: 'error',
42
+ message: 'Health check failed',
43
+ error: err.message
44
+ });
45
+ }
46
+ }
47
+
48
+ // Usage in your server:
49
+ // import { healthHandler } from './cerber/health-route.js';
50
+ // app.get('{{HEALTH_ENDPOINT}}', healthHandler);
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Generated by Cerber init
3
+
4
+ npm run cerber:guardian