coderifts 1.5.0 → 1.7.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.
- package/README.md +20 -6
- package/dist/cli.js +91858 -0
- package/package.json +21 -8
- package/bin/coderifts.js +0 -45
- package/src/cloud.js +0 -51
- package/src/commands/diff.js +0 -237
- package/src/commands/init.js +0 -223
- package/src/commands/login.js +0 -38
- package/src/config.js +0 -65
- package/src/output/json.js +0 -10
- package/src/output/terminal.js +0 -156
package/src/config.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const yaml = require('js-yaml');
|
|
6
|
-
const os = require('os');
|
|
7
|
-
|
|
8
|
-
const CONFIG_DIR = path.join(os.homedir(), '.coderifts');
|
|
9
|
-
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Load the project .coderifts.yml config from the given path or cwd.
|
|
13
|
-
*/
|
|
14
|
-
function loadProjectConfig(configPath) {
|
|
15
|
-
const candidates = configPath
|
|
16
|
-
? [configPath]
|
|
17
|
-
: [
|
|
18
|
-
path.join(process.cwd(), '.coderifts.yml'),
|
|
19
|
-
path.join(process.cwd(), '.coderifts.yaml'),
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
for (const p of candidates) {
|
|
23
|
-
if (fs.existsSync(p)) {
|
|
24
|
-
try {
|
|
25
|
-
const raw = fs.readFileSync(p, 'utf-8');
|
|
26
|
-
return yaml.load(raw) || {};
|
|
27
|
-
} catch {
|
|
28
|
-
return {};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Load the user's global config (~/.coderifts/config.json).
|
|
37
|
-
*/
|
|
38
|
-
function loadUserConfig() {
|
|
39
|
-
if (!fs.existsSync(CONFIG_FILE)) return {};
|
|
40
|
-
try {
|
|
41
|
-
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
|
|
42
|
-
} catch {
|
|
43
|
-
return {};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Save the user's global config.
|
|
49
|
-
*/
|
|
50
|
-
function saveUserConfig(config) {
|
|
51
|
-
if (!fs.existsSync(CONFIG_DIR)) {
|
|
52
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
53
|
-
}
|
|
54
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Get the stored API key.
|
|
59
|
-
*/
|
|
60
|
-
function getApiKey() {
|
|
61
|
-
const userConfig = loadUserConfig();
|
|
62
|
-
return userConfig.api_key || process.env.CODERIFTS_API_KEY || null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
module.exports = { loadProjectConfig, loadUserConfig, saveUserConfig, getApiKey, CONFIG_DIR, CONFIG_FILE };
|
package/src/output/json.js
DELETED
package/src/output/terminal.js
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
const Table = require('cli-table3');
|
|
5
|
-
|
|
6
|
-
// Respect NO_COLOR env var
|
|
7
|
-
if (process.env.NO_COLOR) {
|
|
8
|
-
chalk.level = 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const RISK_COLORS = {
|
|
12
|
-
minimal: chalk.green,
|
|
13
|
-
low: chalk.green,
|
|
14
|
-
moderate: chalk.yellow,
|
|
15
|
-
high: chalk.red,
|
|
16
|
-
critical: chalk.bgRed.white,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const SEVERITY_ICONS = {
|
|
20
|
-
high: chalk.red('●'),
|
|
21
|
-
medium: chalk.yellow('●'),
|
|
22
|
-
low: chalk.blue('●'),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
function riskEmoji(level) {
|
|
26
|
-
switch (level) {
|
|
27
|
-
case 'minimal': return chalk.green('●');
|
|
28
|
-
case 'low': return chalk.green('●');
|
|
29
|
-
case 'moderate': return chalk.yellow('●');
|
|
30
|
-
case 'high': return chalk.red('●');
|
|
31
|
-
case 'critical': return chalk.bgRed.white(' ● ');
|
|
32
|
-
default: return '●';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function semverEmoji(suggestion) {
|
|
37
|
-
switch (suggestion) {
|
|
38
|
-
case 'major': return chalk.red('● MAJOR');
|
|
39
|
-
case 'minor': return chalk.yellow('● MINOR');
|
|
40
|
-
case 'patch': return chalk.green('● PATCH');
|
|
41
|
-
default: return chalk.dim('none');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Render the full terminal report.
|
|
47
|
-
*/
|
|
48
|
-
function renderTerminal(result) {
|
|
49
|
-
const lines = [];
|
|
50
|
-
|
|
51
|
-
// ── Header box ──
|
|
52
|
-
const color = RISK_COLORS[result.risk_level] || chalk.white;
|
|
53
|
-
lines.push('');
|
|
54
|
-
lines.push(chalk.bold(' ╔══════════════════════════════════════════╗'));
|
|
55
|
-
lines.push(chalk.bold(' ║ CodeRifts — API Breaking Change Report ║'));
|
|
56
|
-
lines.push(chalk.bold(' ╠══════════════════════════════════════════╣'));
|
|
57
|
-
lines.push(chalk.bold(` ║ Risk Score: ${color(`${result.risk_score}/100 (${capitalize(result.risk_level)})`).padEnd(32)}║`));
|
|
58
|
-
lines.push(chalk.bold(` ║ Semver: ${semverEmoji(result.semver_suggestion).padEnd(32)}║`));
|
|
59
|
-
lines.push(chalk.bold(` ║ Breaking: ${String(result.stats?.breaking_count || 0).padEnd(22)}║`));
|
|
60
|
-
lines.push(chalk.bold(` ║ Non-Breaking: ${String(result.stats?.non_breaking_count || 0).padEnd(22)}║`));
|
|
61
|
-
lines.push(chalk.bold(` ║ Security: ${String(result.stats?.security_count || 0).padEnd(22)}║`));
|
|
62
|
-
lines.push(chalk.bold(' ╚══════════════════════════════════════════╝'));
|
|
63
|
-
lines.push('');
|
|
64
|
-
|
|
65
|
-
// ── Risk Dimensions ──
|
|
66
|
-
if (result.risk_dimensions) {
|
|
67
|
-
const dims = result.risk_dimensions;
|
|
68
|
-
lines.push(chalk.bold(' Risk Dimensions:'));
|
|
69
|
-
const dimTable = new Table({
|
|
70
|
-
head: ['Dimension', 'Score'],
|
|
71
|
-
style: { head: ['cyan'], border: ['dim'] },
|
|
72
|
-
colWidths: [25, 10],
|
|
73
|
-
});
|
|
74
|
-
dimTable.push(
|
|
75
|
-
['Revenue Impact', dims.revenue_impact || 0],
|
|
76
|
-
['Blast Radius', dims.blast_radius || 0],
|
|
77
|
-
['App Compatibility', dims.app_compatibility || 0],
|
|
78
|
-
['Security', dims.security || 0],
|
|
79
|
-
);
|
|
80
|
-
lines.push(dimTable.toString());
|
|
81
|
-
lines.push('');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ── Breaking Changes ──
|
|
85
|
-
if (result.breaking_changes && result.breaking_changes.length > 0) {
|
|
86
|
-
lines.push(chalk.bold.red(` Breaking Changes (${result.breaking_changes.length}):`));
|
|
87
|
-
const breakTable = new Table({
|
|
88
|
-
head: ['Type', 'Path', 'Severity'],
|
|
89
|
-
style: { head: ['red'], border: ['dim'] },
|
|
90
|
-
colWidths: [25, 25, 12],
|
|
91
|
-
});
|
|
92
|
-
for (const change of result.breaking_changes) {
|
|
93
|
-
const sev = SEVERITY_ICONS[change.severity] || change.severity;
|
|
94
|
-
breakTable.push([
|
|
95
|
-
change.type || '',
|
|
96
|
-
`${change.method || ''} ${change.path || ''}`.trim(),
|
|
97
|
-
`${sev} ${change.severity || ''}`,
|
|
98
|
-
]);
|
|
99
|
-
}
|
|
100
|
-
lines.push(breakTable.toString());
|
|
101
|
-
lines.push('');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ── Non-Breaking Changes ──
|
|
105
|
-
if (result.non_breaking_changes && result.non_breaking_changes.length > 0) {
|
|
106
|
-
lines.push(chalk.bold.green(` Non-Breaking Changes (${result.non_breaking_changes.length}):`));
|
|
107
|
-
const nbTable = new Table({
|
|
108
|
-
head: ['Type', 'Path', 'Description'],
|
|
109
|
-
style: { head: ['green'], border: ['dim'] },
|
|
110
|
-
colWidths: [25, 25, 25],
|
|
111
|
-
});
|
|
112
|
-
for (const change of result.non_breaking_changes.slice(0, 10)) {
|
|
113
|
-
nbTable.push([
|
|
114
|
-
change.type || '',
|
|
115
|
-
`${change.method || ''} ${change.path || ''}`.trim(),
|
|
116
|
-
(change.description || '').substring(0, 22),
|
|
117
|
-
]);
|
|
118
|
-
}
|
|
119
|
-
lines.push(nbTable.toString());
|
|
120
|
-
lines.push('');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ── Security Findings ──
|
|
124
|
-
if (result.security_findings && result.security_findings.length > 0) {
|
|
125
|
-
lines.push(chalk.bold.yellow(` Security Findings (${result.security_findings.length}):`));
|
|
126
|
-
for (const finding of result.security_findings) {
|
|
127
|
-
lines.push(` ${chalk.yellow('⚠')} ${finding.description || finding.type || JSON.stringify(finding)}`);
|
|
128
|
-
}
|
|
129
|
-
lines.push('');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// ── Policy Violations ──
|
|
133
|
-
if (result.policy_violations && result.policy_violations.length > 0) {
|
|
134
|
-
lines.push(chalk.bold.red(` Policy Violations (${result.policy_violations.length}):`));
|
|
135
|
-
for (const v of result.policy_violations) {
|
|
136
|
-
lines.push(` ${chalk.red('✗')} ${v.message || v.rule || JSON.stringify(v)}`);
|
|
137
|
-
}
|
|
138
|
-
lines.push('');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ── Should Block ──
|
|
142
|
-
if (result.should_block) {
|
|
143
|
-
lines.push(chalk.bgRed.white.bold(' ✗ BLOCKED — breaking changes exceed threshold '));
|
|
144
|
-
} else {
|
|
145
|
-
lines.push(chalk.green.bold(' ✓ PASSED — within acceptable risk threshold'));
|
|
146
|
-
}
|
|
147
|
-
lines.push('');
|
|
148
|
-
|
|
149
|
-
return lines.join('\n');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function capitalize(s) {
|
|
153
|
-
return s ? s.charAt(0).toUpperCase() + s.slice(1) : '';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
module.exports = { renderTerminal };
|