reverse-engine 0.1.0 → 0.2.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.
Potentially problematic release.
This version of reverse-engine might be problematic. Click here for more details.
- package/dist/cli/index.js +54 -2
- package/dist/native.d.ts +11 -0
- package/dist/native.js +52 -0
- package/package.json +9 -1
package/dist/cli/index.js
CHANGED
|
@@ -2,10 +2,38 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { execFileSync } from 'child_process';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { createRequire } from 'module';
|
|
5
9
|
import { analyze } from '../analyzer/index.js';
|
|
6
10
|
import { generateReport } from '../docgen/index.js';
|
|
7
11
|
import { generateTests } from '../testgen/index.js';
|
|
12
|
+
// ─── 네이티브 바이너리 탐색 ───
|
|
13
|
+
function findNativeBinary() {
|
|
14
|
+
const key = `${process.platform}-${process.arch}`;
|
|
15
|
+
const pkgName = `reverse-engine-${key}`;
|
|
16
|
+
const binName = process.platform === 'win32' ? 'reverseng.exe' : 'reverseng';
|
|
17
|
+
try {
|
|
18
|
+
const req = createRequire(import.meta.url);
|
|
19
|
+
const pkgJsonPath = req.resolve(`${pkgName}/package.json`);
|
|
20
|
+
const binPath = join(dirname(pkgJsonPath), 'bin', binName);
|
|
21
|
+
if (existsSync(binPath))
|
|
22
|
+
return binPath;
|
|
23
|
+
}
|
|
24
|
+
catch { /* not installed */ }
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function runNative(args) {
|
|
28
|
+
if (!nativeBin)
|
|
29
|
+
return;
|
|
30
|
+
execFileSync(nativeBin, args, { stdio: 'inherit' });
|
|
31
|
+
}
|
|
32
|
+
const nativeBin = findNativeBinary();
|
|
8
33
|
const program = new Command();
|
|
34
|
+
if (nativeBin) {
|
|
35
|
+
console.log(chalk.dim(`⚡ 네이티브 Rust 바이너리 사용중`));
|
|
36
|
+
}
|
|
9
37
|
program
|
|
10
38
|
.name('reverse-engine')
|
|
11
39
|
.version('0.1.0')
|
|
@@ -18,6 +46,11 @@ program
|
|
|
18
46
|
.option('--include <patterns>', '포함 패턴 (쉼표 구분)', 'src/**/*.{ts,tsx,js,jsx,vue}')
|
|
19
47
|
.option('--output <dir>', '출력 디렉토리', './output')
|
|
20
48
|
.action(async (sourcePath, opts) => {
|
|
49
|
+
// 네이티브 바이너리가 있으면 Rust 사용 (5~10x 빠름)
|
|
50
|
+
if (nativeBin) {
|
|
51
|
+
runNative(['analyze', sourcePath, '--framework', opts.framework]);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
21
54
|
console.log(chalk.green('▶'), '코드 분석 시작:', chalk.cyan(sourcePath));
|
|
22
55
|
const result = await analyze(sourcePath, {
|
|
23
56
|
framework: opts.framework,
|
|
@@ -73,8 +106,27 @@ program
|
|
|
73
106
|
.option('--output <dir>', '출력 디렉토리', './output')
|
|
74
107
|
.option('--framework <name>', '프레임워크', 'auto')
|
|
75
108
|
.action(async (opts) => {
|
|
76
|
-
console.log(chalk.green('\n◆'), 'ReversEngine 전체 파이프라인
|
|
77
|
-
// Step 1: 분석
|
|
109
|
+
console.log(chalk.green('\n◆'), 'ReversEngine 전체 파이프라인 시작', nativeBin ? chalk.dim('(⚡ native)') : '', '\n');
|
|
110
|
+
// Step 1: 분석 — 네이티브가 있으면 Rust 사용
|
|
111
|
+
if (nativeBin) {
|
|
112
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
113
|
+
runNative(['analyze', opts.source, '--framework', opts.framework || 'auto']);
|
|
114
|
+
const analysisPath = `${opts.output}/analysis.json`;
|
|
115
|
+
if (existsSync(analysisPath)) {
|
|
116
|
+
const result = JSON.parse(await readFile(analysisPath, 'utf-8'));
|
|
117
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
118
|
+
const reports = await generateReport(result, { outputDir: `${opts.output}/reports` });
|
|
119
|
+
console.log(chalk.green('✓'), '리포트 생성 완료!');
|
|
120
|
+
reports.forEach((p) => console.log(` → ${chalk.cyan(p)}`));
|
|
121
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
122
|
+
const tests = await generateTests(result, { outputDir: `${opts.output}/tests` });
|
|
123
|
+
console.log(chalk.green('✓'), `테스트 생성 완료! (${tests.length}개)`);
|
|
124
|
+
tests.forEach((p) => console.log(` → ${chalk.cyan(p)}`));
|
|
125
|
+
}
|
|
126
|
+
console.log(chalk.green('\n✓'), '전체 파이프라인 완료!', chalk.cyan(opts.output), '\n');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// JS fallback — Step 1: 분석
|
|
78
130
|
console.log(chalk.gray('━'.repeat(50)));
|
|
79
131
|
const result = await analyze(opts.source, { framework: opts.framework });
|
|
80
132
|
console.log(chalk.green('✓'), `분석 완료: 컴포넌트 ${result.components.length}, 함수 ${result.functions.length}, API ${result.apiClients.length}, 라우트 ${result.routes.length}`);
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 플랫폼에 맞는 네이티브 Rust 바이너리를 찾아 반환
|
|
3
|
+
* 없으면 null → JS fallback 사용
|
|
4
|
+
*/
|
|
5
|
+
import { type ExecFileSyncOptions } from 'child_process';
|
|
6
|
+
/** 네이티브 바이너리 경로를 찾는다 */
|
|
7
|
+
export declare function findNativeBinary(): string | null;
|
|
8
|
+
/** 네이티브 바이너리로 명령어 실행 */
|
|
9
|
+
export declare function execNative(args: string[], options?: ExecFileSyncOptions): string;
|
|
10
|
+
/** 네이티브 바이너리 사용 가능 여부 */
|
|
11
|
+
export declare function hasNativeBinary(): boolean;
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 플랫폼에 맞는 네이티브 Rust 바이너리를 찾아 반환
|
|
3
|
+
* 없으면 null → JS fallback 사용
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { join, dirname } from 'path';
|
|
7
|
+
import { execFileSync } from 'child_process';
|
|
8
|
+
const PLATFORMS = {
|
|
9
|
+
'win32-x64': 'reverse-engine-win32-x64',
|
|
10
|
+
'win32-arm64': 'reverse-engine-win32-arm64',
|
|
11
|
+
'linux-x64': 'reverse-engine-linux-x64',
|
|
12
|
+
'linux-arm64': 'reverse-engine-linux-arm64',
|
|
13
|
+
'darwin-x64': 'reverse-engine-darwin-x64',
|
|
14
|
+
'darwin-arm64': 'reverse-engine-darwin-arm64',
|
|
15
|
+
};
|
|
16
|
+
/** 네이티브 바이너리 경로를 찾는다 */
|
|
17
|
+
export function findNativeBinary() {
|
|
18
|
+
const key = `${process.platform}-${process.arch}`;
|
|
19
|
+
const pkgName = PLATFORMS[key];
|
|
20
|
+
if (!pkgName)
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
// optionalDependencies에서 설치된 패키지 경로
|
|
24
|
+
const pkgJson = require.resolve(`${pkgName}/package.json`);
|
|
25
|
+
const pkgDir = dirname(pkgJson);
|
|
26
|
+
const pkg = JSON.parse(require('fs').readFileSync(pkgJson, 'utf-8'));
|
|
27
|
+
const binPath = join(pkgDir, pkg.main || (process.platform === 'win32' ? 'bin/reverseng.exe' : 'bin/reverseng'));
|
|
28
|
+
if (existsSync(binPath)) {
|
|
29
|
+
return binPath;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// 패키지가 설치되지 않음 → fallback
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/** 네이티브 바이너리로 명령어 실행 */
|
|
38
|
+
export function execNative(args, options) {
|
|
39
|
+
const binPath = findNativeBinary();
|
|
40
|
+
if (!binPath) {
|
|
41
|
+
throw new Error('네이티브 바이너리를 찾을 수 없습니다');
|
|
42
|
+
}
|
|
43
|
+
return execFileSync(binPath, args, {
|
|
44
|
+
encoding: 'utf-8',
|
|
45
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
46
|
+
...options,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** 네이티브 바이너리 사용 가능 여부 */
|
|
50
|
+
export function hasNativeBinary() {
|
|
51
|
+
return findNativeBinary() !== null;
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reverse-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "웹 서비스 역분석 자동화 도구 - 소스코드 분석, 문서 생성, 테스트 자동화",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reverse-engineering",
|
|
@@ -61,6 +61,14 @@
|
|
|
61
61
|
"typescript": "^5.7.0",
|
|
62
62
|
"tsx": "^4.19.0"
|
|
63
63
|
},
|
|
64
|
+
"optionalDependencies": {
|
|
65
|
+
"reverse-engine-win32-x64": "0.2.0",
|
|
66
|
+
"reverse-engine-win32-arm64": "0.2.0",
|
|
67
|
+
"reverse-engine-linux-x64": "0.2.0",
|
|
68
|
+
"reverse-engine-linux-arm64": "0.2.0",
|
|
69
|
+
"reverse-engine-darwin-x64": "0.2.0",
|
|
70
|
+
"reverse-engine-darwin-arm64": "0.2.0"
|
|
71
|
+
},
|
|
64
72
|
"engines": {
|
|
65
73
|
"node": ">=18.0.0"
|
|
66
74
|
}
|