codeant-cli 0.1.5 → 0.1.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.
- package/dist/239.index.js +1 -0
- package/dist/701.index.js +1 -0
- package/dist/935.index.js +1 -0
- package/dist/index.js +12 -0
- package/dist/package.json +3 -0
- package/package.json +12 -4
- package/src/commands/getBaseUrl.js +0 -25
- package/src/commands/login.js +0 -124
- package/src/commands/logout.js +0 -30
- package/src/commands/review.js +0 -239
- package/src/commands/secrets.js +0 -268
- package/src/commands/securityAnalysis.js +0 -284
- package/src/commands/setBaseUrl.js +0 -37
- package/src/commands/staticAnalysis.js +0 -405
- package/src/components/ReviewUI.js +0 -127
- package/src/components/Welcome.js +0 -143
- package/src/index.js +0 -202
- package/src/tools/bashTool.js +0 -17
- package/src/tools/executeTool.js +0 -35
- package/src/tools/globTool.js +0 -9
- package/src/tools/grepTool.js +0 -18
- package/src/tools/lsTool.js +0 -7
- package/src/tools/readTool.js +0 -12
- package/src/utils/commonApiHelper.js +0 -101
- package/src/utils/config.js +0 -42
- package/src/utils/fetchApi.js +0 -42
- package/src/utils/gitDiffHelper.js +0 -774
- package/src/utils/reviewApiHelper.js +0 -139
- package/src/utils/secretsApiHelper.js +0 -134
- package/src/utils/securityAnalysisApiHelper.js +0 -119
- package/src/utils/staticAnalysisApiHelper.js +0 -119
package/src/index.js
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { program } from 'commander';
|
|
4
|
-
import { render } from 'ink';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import Secrets from './commands/secrets.js';
|
|
7
|
-
import SetBaseUrl from './commands/setBaseUrl.js';
|
|
8
|
-
import GetBaseUrl from './commands/getBaseUrl.js';
|
|
9
|
-
import Login from './commands/login.js';
|
|
10
|
-
import Logout from './commands/logout.js';
|
|
11
|
-
import StaticAnalysis from './commands/staticAnalysis.js';
|
|
12
|
-
import SecurityAnalysis from './commands/securityAnalysis.js';
|
|
13
|
-
import Review from './commands/review.js';
|
|
14
|
-
import Welcome from './components/Welcome.js';
|
|
15
|
-
|
|
16
|
-
// Show welcome animation if no arguments provided
|
|
17
|
-
if (process.argv.length === 2) {
|
|
18
|
-
render(React.createElement(Welcome));
|
|
19
|
-
} else {
|
|
20
|
-
program
|
|
21
|
-
.name('codeant')
|
|
22
|
-
.description('Code review CLI tool')
|
|
23
|
-
.version('0.1.3');
|
|
24
|
-
|
|
25
|
-
program
|
|
26
|
-
.command('secrets')
|
|
27
|
-
.description('Scan for secrets in your code')
|
|
28
|
-
.option('--staged', 'Scan only staged files (default)')
|
|
29
|
-
.option('--all', 'Scan all changed files')
|
|
30
|
-
.option('--uncommitted', 'Scan uncommitted changes')
|
|
31
|
-
.option('--last-commit', 'Scan last commit')
|
|
32
|
-
.option('--last-n-commits <n>', 'Scan last n commits (max 5)', parseInt)
|
|
33
|
-
.option('--fail-on <level>', 'Fail only on HIGH, MEDIUM, or all (default: HIGH)', 'HIGH')
|
|
34
|
-
.option('--include <paths>', 'Comma-separated list of file paths regex to include')
|
|
35
|
-
.option('--exclude <paths>', 'Comma-separated list of file paths regex to exclude')
|
|
36
|
-
.action((options) => {
|
|
37
|
-
let scanType = 'staged-only';
|
|
38
|
-
let lastNCommits = 1;
|
|
39
|
-
|
|
40
|
-
if (options.lastNCommits) {
|
|
41
|
-
scanType = 'last-n-commits';
|
|
42
|
-
lastNCommits = Math.min(Math.max(1, options.lastNCommits), 5);
|
|
43
|
-
} else if (options.all) {
|
|
44
|
-
scanType = 'branch-diff';
|
|
45
|
-
} else if (options.uncommitted) {
|
|
46
|
-
scanType = 'uncommitted';
|
|
47
|
-
} else if (options.lastCommit) {
|
|
48
|
-
scanType = 'last-commit';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const include = options.include
|
|
52
|
-
? (Array.isArray(options.include) ? options.include : String(options.include).split(',')).map(s => s.trim()).filter(Boolean)
|
|
53
|
-
: [];
|
|
54
|
-
|
|
55
|
-
const exclude = options.exclude
|
|
56
|
-
? (Array.isArray(options.exclude) ? options.exclude : String(options.exclude).split(',')).map(s => s.trim()).filter(Boolean)
|
|
57
|
-
: [];
|
|
58
|
-
|
|
59
|
-
const failOn = options.failOn?.toUpperCase() || 'HIGH';
|
|
60
|
-
|
|
61
|
-
render(React.createElement(Secrets, { scanType, failOn, include, exclude, lastNCommits }));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
program
|
|
65
|
-
.command('static-analysis')
|
|
66
|
-
.description('Run static analysis on your code')
|
|
67
|
-
.option('--staged', 'Scan only staged files (default)')
|
|
68
|
-
.option('--all', 'Scan all changed files')
|
|
69
|
-
.option('--uncommitted', 'Scan uncommitted changes')
|
|
70
|
-
.option('--last-commit', 'Scan last commit')
|
|
71
|
-
.option('--last-n-commits <n>', 'Scan last n commits (max 5)', parseInt)
|
|
72
|
-
.option('--fail-on <level>', 'Fail on issues at or above this level: BLOCKER, CRITICAL, MAJOR, MINOR, INFO (default: CRITICAL)', 'CRITICAL')
|
|
73
|
-
.option('--auto-fix', 'Automatically apply fixes when available')
|
|
74
|
-
.option('--include <paths>', 'Comma-separated list of file paths regex to include')
|
|
75
|
-
.option('--exclude <paths>', 'Comma-separated list of file paths regex to exclude')
|
|
76
|
-
.action((options) => {
|
|
77
|
-
let scanType = 'staged-only';
|
|
78
|
-
let lastNCommits = 1;
|
|
79
|
-
|
|
80
|
-
if (options.lastNCommits) {
|
|
81
|
-
scanType = 'last-n-commits';
|
|
82
|
-
lastNCommits = Math.min(Math.max(1, options.lastNCommits), 5);
|
|
83
|
-
} else if (options.all) {
|
|
84
|
-
scanType = 'branch-diff';
|
|
85
|
-
} else if (options.uncommitted) {
|
|
86
|
-
scanType = 'uncommitted';
|
|
87
|
-
} else if (options.lastCommit) {
|
|
88
|
-
scanType = 'last-commit';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const include = options.include
|
|
92
|
-
? (Array.isArray(options.include) ? options.include : String(options.include).split(',')).map(s => s.trim()).filter(Boolean)
|
|
93
|
-
: [];
|
|
94
|
-
|
|
95
|
-
const exclude = options.exclude
|
|
96
|
-
? (Array.isArray(options.exclude) ? options.exclude : String(options.exclude).split(',')).map(s => s.trim()).filter(Boolean)
|
|
97
|
-
: [];
|
|
98
|
-
|
|
99
|
-
const failOn = options.failOn?.toUpperCase() || 'CRITICAL';
|
|
100
|
-
const autoFix = options.autoFix || false;
|
|
101
|
-
render(React.createElement(StaticAnalysis, {scanType, failOn, include, exclude, autoFix, lastNCommits}));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
program
|
|
105
|
-
.command('security-analysis')
|
|
106
|
-
.description('Run security analysis on your code')
|
|
107
|
-
.option('--staged', 'Scan only staged files (default)')
|
|
108
|
-
.option('--all', 'Scan all changed files')
|
|
109
|
-
.option('--uncommitted', 'Scan uncommitted changes')
|
|
110
|
-
.option('--last-commit', 'Scan last commit')
|
|
111
|
-
.option('--last-n-commits <n>', 'Scan last n commits (max 5)', parseInt)
|
|
112
|
-
.option('--fail-on <level>', 'Fail on issues at or above this level: BLOCKER, CRITICAL, MAJOR, MINOR, INFO (default: CRITICAL)', 'CRITICAL')
|
|
113
|
-
.option('--include <paths>', 'Comma-separated list of file paths regex to include')
|
|
114
|
-
.option('--exclude <paths>', 'Comma-separated list of file paths regex to exclude')
|
|
115
|
-
.action((options) => {
|
|
116
|
-
let scanType = 'staged-only';
|
|
117
|
-
let lastNCommits = 1;
|
|
118
|
-
|
|
119
|
-
if (options.lastNCommits) {
|
|
120
|
-
scanType = 'last-n-commits';
|
|
121
|
-
lastNCommits = Math.min(Math.max(1, options.lastNCommits), 5);
|
|
122
|
-
} else if (options.all) {
|
|
123
|
-
scanType = 'branch-diff';
|
|
124
|
-
} else if (options.uncommitted) {
|
|
125
|
-
scanType = 'uncommitted';
|
|
126
|
-
} else if (options.lastCommit) {
|
|
127
|
-
scanType = 'last-commit';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const include = options.include
|
|
131
|
-
? (Array.isArray(options.include) ? options.include : String(options.include).split(',')).map(s => s.trim()).filter(Boolean)
|
|
132
|
-
: [];
|
|
133
|
-
|
|
134
|
-
const exclude = options.exclude
|
|
135
|
-
? (Array.isArray(options.exclude) ? options.exclude : String(options.exclude).split(',')).map(s => s.trim()).filter(Boolean)
|
|
136
|
-
: [];
|
|
137
|
-
|
|
138
|
-
const failOn = options.failOn?.toUpperCase() || 'HIGH';
|
|
139
|
-
|
|
140
|
-
render(React.createElement(SecurityAnalysis, { scanType, failOn, include, exclude, lastNCommits }));
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
program
|
|
144
|
-
.command('review')
|
|
145
|
-
.description('Run AI-powered code review')
|
|
146
|
-
.option('--staged', 'Review only staged files (default)')
|
|
147
|
-
.option('--all', 'Review all changed files')
|
|
148
|
-
.option('--uncommitted', 'Review uncommitted changes')
|
|
149
|
-
.option('--last-commit', 'Review last commit')
|
|
150
|
-
.option('--last-n-commits <n>', 'Review last n commits (max 5)', parseInt)
|
|
151
|
-
.option('--fail-on <level>', 'Fail on issues at or above this level: BLOCKER, CRITICAL, MAJOR, MINOR, INFO (default: CRITICAL)', 'CRITICAL')
|
|
152
|
-
.action((options) => {
|
|
153
|
-
let scanType = 'staged-only';
|
|
154
|
-
let lastNCommits = 1;
|
|
155
|
-
|
|
156
|
-
if (options.lastNCommits) {
|
|
157
|
-
scanType = 'last-n-commits';
|
|
158
|
-
// Clamp between 1 and 5
|
|
159
|
-
lastNCommits = Math.min(Math.max(1, options.lastNCommits), 5);
|
|
160
|
-
} else if (options.all) {
|
|
161
|
-
scanType = 'branch-diff';
|
|
162
|
-
} else if (options.uncommitted) {
|
|
163
|
-
scanType = 'uncommitted';
|
|
164
|
-
} else if (options.lastCommit) {
|
|
165
|
-
scanType = 'last-commit';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const failOn = options.failOn?.toUpperCase() || 'CRITICAL';
|
|
169
|
-
|
|
170
|
-
render(React.createElement(Review, { scanType, lastNCommits, failOn }));
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
program
|
|
174
|
-
.command('set-base-url <url>')
|
|
175
|
-
.description('Set the API base URL')
|
|
176
|
-
.action((url) => {
|
|
177
|
-
render(React.createElement(SetBaseUrl, { url }));
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
program
|
|
181
|
-
.command('get-base-url')
|
|
182
|
-
.description('Show the current API base URL')
|
|
183
|
-
.action(() => {
|
|
184
|
-
render(React.createElement(GetBaseUrl));
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
program
|
|
188
|
-
.command('login')
|
|
189
|
-
.description('Login to CodeAnt')
|
|
190
|
-
.action(() => {
|
|
191
|
-
render(React.createElement(Login));
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
program
|
|
195
|
-
.command('logout')
|
|
196
|
-
.description('Logout from CodeAnt')
|
|
197
|
-
.action(() => {
|
|
198
|
-
render(React.createElement(Logout));
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
program.parse();
|
|
202
|
-
}
|
package/src/tools/bashTool.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { exec } from 'child_process';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
|
|
4
|
-
const execAsync = promisify(exec);
|
|
5
|
-
|
|
6
|
-
export async function bashTool(args, cwd) {
|
|
7
|
-
const cmd = args.command;
|
|
8
|
-
if (!cmd) {
|
|
9
|
-
return 'Error: Bash tool requires a command argument';
|
|
10
|
-
}
|
|
11
|
-
try {
|
|
12
|
-
const { stdout } = await execAsync(cmd, { cwd });
|
|
13
|
-
return stdout;
|
|
14
|
-
} catch (err) {
|
|
15
|
-
return `Error: ${err.message}`;
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/tools/executeTool.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { readTool } from './readTool.js';
|
|
2
|
-
import { globTool } from './globTool.js';
|
|
3
|
-
import { grepTool } from './grepTool.js';
|
|
4
|
-
import { lsTool } from './lsTool.js';
|
|
5
|
-
import { bashTool } from './bashTool.js';
|
|
6
|
-
|
|
7
|
-
export async function executeTool(toolCall, cwd) {
|
|
8
|
-
const { name, args } = toolCall;
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
if (name === 'Read') {
|
|
12
|
-
return await readTool(args, cwd);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (name === 'Glob') {
|
|
16
|
-
return await globTool(args, cwd);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (name === 'Grep') {
|
|
20
|
-
return await grepTool(args, cwd);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (name === 'LS') {
|
|
24
|
-
return await lsTool(args, cwd);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (name === 'Bash') {
|
|
28
|
-
return await bashTool(args, cwd);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return `Unknown tool: ${name}`;
|
|
32
|
-
} catch (err) {
|
|
33
|
-
return `Error: ${err.message}`;
|
|
34
|
-
}
|
|
35
|
-
}
|
package/src/tools/globTool.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
|
|
3
|
-
export async function globTool(args, cwd) {
|
|
4
|
-
const { globSync } = await import('glob');
|
|
5
|
-
const pattern = path.resolve(cwd, args.pattern);
|
|
6
|
-
const matches = globSync(pattern);
|
|
7
|
-
if (!matches.length) return 'No files found';
|
|
8
|
-
return matches.map(m => path.relative(cwd, m)).join('\n');
|
|
9
|
-
}
|
package/src/tools/grepTool.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
export async function grepTool(args, cwd) {
|
|
5
|
-
const target = args.path ? path.resolve(cwd, args.path) : cwd;
|
|
6
|
-
const result = await new Promise((resolve) => {
|
|
7
|
-
const proc = spawn('grep', ['-rn', args.pattern, target], {
|
|
8
|
-
cwd,
|
|
9
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
10
|
-
timeout: 30000,
|
|
11
|
-
});
|
|
12
|
-
let stdout = '';
|
|
13
|
-
proc.stdout.on('data', (data) => { stdout += data; });
|
|
14
|
-
proc.on('close', () => resolve(stdout.trim() || 'No matches found'));
|
|
15
|
-
proc.on('error', () => resolve('No matches found'));
|
|
16
|
-
});
|
|
17
|
-
return result;
|
|
18
|
-
}
|
package/src/tools/lsTool.js
DELETED
package/src/tools/readTool.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
export async function readTool(args, cwd) {
|
|
5
|
-
const filePath = path.resolve(cwd, args.file_path);
|
|
6
|
-
const content = await fs.promises.readFile(filePath, 'utf8');
|
|
7
|
-
const lines = content.split('\n');
|
|
8
|
-
const offset = args.offset || 1;
|
|
9
|
-
const limit = args.limit || lines.length;
|
|
10
|
-
const selected = lines.slice(offset - 1, offset - 1 + limit);
|
|
11
|
-
return selected.map((line, i) => ` ${offset + i}\t${line}`).join('\n');
|
|
12
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import GitDiffHelper from './gitDiffHelper.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Common base class for API helpers that transform git diff data
|
|
5
|
-
* Contains shared functionality for filtering and retrieving files
|
|
6
|
-
*/
|
|
7
|
-
class CommonApiHelper {
|
|
8
|
-
constructor(workspacePath) {
|
|
9
|
-
this.workspacePath = workspacePath;
|
|
10
|
-
this.gitHelper = new GitDiffHelper(workspacePath);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async init() {
|
|
14
|
-
await this.gitHelper.init();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Get staged files formatted for the API
|
|
19
|
-
* This is used for pre-commit hooks
|
|
20
|
-
*/
|
|
21
|
-
async getStagedFilesForApi() {
|
|
22
|
-
const diffs = await this.gitHelper.getDiffBasedOnReviewConfig({ type: 'staged-only' });
|
|
23
|
-
return this._transformDiffsToApiFormat(diffs);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get all changed files formatted for the API
|
|
28
|
-
*/
|
|
29
|
-
async getChangedFilesForApi() {
|
|
30
|
-
const diffs = await this.gitHelper.getDiffBasedOnReviewConfig({ type: 'branch-diff' });
|
|
31
|
-
return this._transformDiffsToApiFormat(diffs);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get uncommitted files formatted for the API
|
|
36
|
-
*/
|
|
37
|
-
async getUncommittedFilesForApi() {
|
|
38
|
-
const diffs = await this.gitHelper.getDiffBasedOnReviewConfig({ type: 'uncommitted' });
|
|
39
|
-
return this._transformDiffsToApiFormat(diffs);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get last commit files formatted for the API
|
|
44
|
-
*/
|
|
45
|
-
async getLastCommitFilesForApi() {
|
|
46
|
-
const diffs = await this.gitHelper.getDiffBasedOnReviewConfig({ type: 'last-commit' });
|
|
47
|
-
return this._transformDiffsToApiFormat(diffs);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get last n commits files formatted for the API
|
|
52
|
-
* @param {number} n - Number of commits to include
|
|
53
|
-
*/
|
|
54
|
-
async getLastNCommitsFilesForApi(n = 1) {
|
|
55
|
-
const diffs = await this.gitHelper.getDiffBasedOnReviewConfig({
|
|
56
|
-
type: 'last-n-commits',
|
|
57
|
-
commits: n
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
return this._transformDiffsToApiFormat(diffs);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Transform diff info array to API format
|
|
65
|
-
* Must be implemented by subclasses
|
|
66
|
-
*/
|
|
67
|
-
_transformDiffsToApiFormat(diffs) {
|
|
68
|
-
throw new Error('_transformDiffsToApiFormat must be implemented by subclass');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get files based on scan type
|
|
74
|
-
* Returns the raw array - child classes handle filtering and wrapping
|
|
75
|
-
* @param {string} type - Type of scan (staged-only, branch-diff, etc.)
|
|
76
|
-
* @param {Object} options - Additional options
|
|
77
|
-
* @param {number} options.lastNCommits - Number of commits for last-n-commits type
|
|
78
|
-
*/
|
|
79
|
-
async getFilesForType(type = 'staged-only', options = {}) {
|
|
80
|
-
switch (type) {
|
|
81
|
-
case 'staged-only':
|
|
82
|
-
return await this.getStagedFilesForApi();
|
|
83
|
-
case 'branch-diff':
|
|
84
|
-
return await this.getChangedFilesForApi();
|
|
85
|
-
case 'uncommitted':
|
|
86
|
-
return await this.getUncommittedFilesForApi();
|
|
87
|
-
case 'last-commit':
|
|
88
|
-
return await this.getLastCommitFilesForApi();
|
|
89
|
-
case 'last-n-commits':
|
|
90
|
-
return await this.getLastNCommitsFilesForApi(options.lastNCommits || 1);
|
|
91
|
-
default:
|
|
92
|
-
return await this.getStagedFilesForApi();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
getGitRoot() {
|
|
97
|
-
return this.gitHelper.getGitRoot();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export default CommonApiHelper;
|
package/src/utils/config.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
|
|
5
|
-
const CONFIG_DIR = path.join(os.homedir(), '.codeant');
|
|
6
|
-
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
7
|
-
|
|
8
|
-
const ensureConfigDir = () => {
|
|
9
|
-
if (!fs.existsSync(CONFIG_DIR)) {
|
|
10
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const loadConfig = () => {
|
|
15
|
-
try {
|
|
16
|
-
if (fs.existsSync(CONFIG_FILE)) {
|
|
17
|
-
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
18
|
-
return JSON.parse(data);
|
|
19
|
-
}
|
|
20
|
-
} catch (err) {
|
|
21
|
-
console.error('Error loading config:', err.message);
|
|
22
|
-
}
|
|
23
|
-
return {};
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const saveConfig = (config) => {
|
|
27
|
-
ensureConfigDir();
|
|
28
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const getConfigValue = (key) => {
|
|
32
|
-
const config = loadConfig();
|
|
33
|
-
return config[key];
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const setConfigValue = (key, value) => {
|
|
37
|
-
const config = loadConfig();
|
|
38
|
-
config[key] = value;
|
|
39
|
-
saveConfig(config);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export { loadConfig, saveConfig, getConfigValue, setConfigValue, CONFIG_FILE };
|
package/src/utils/fetchApi.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { getConfigValue } from './config.js';
|
|
2
|
-
|
|
3
|
-
const getBaseUrl = () => {
|
|
4
|
-
return process.env.CODEANT_API_URL || getConfigValue('baseUrl') || 'https://api.codeant.ai';
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
const fetchApi = async (endpoint, method = 'GET', body = null) => {
|
|
8
|
-
const url = endpoint.startsWith('http') ? endpoint : `${getBaseUrl()}${endpoint}`;
|
|
9
|
-
|
|
10
|
-
const options = {
|
|
11
|
-
method,
|
|
12
|
-
headers: {
|
|
13
|
-
'Content-Type': 'application/json',
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// Add auth token from config or env
|
|
18
|
-
const token = process.env.CODEANT_API_TOKEN || getConfigValue('apiKey');
|
|
19
|
-
if (token) {
|
|
20
|
-
options.headers['Authorization'] = `Bearer ${token}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (body && method !== 'GET') {
|
|
24
|
-
options.body = JSON.stringify(body);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const response = await fetch(url, options);
|
|
29
|
-
const data = await response.json();
|
|
30
|
-
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw new Error(data.message || `HTTP error ${response.status}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return data;
|
|
36
|
-
} catch (err) {
|
|
37
|
-
console.error(`API Error: ${err.message}`);
|
|
38
|
-
throw err;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export { fetchApi };
|