prscan 1.0.2 → 1.0.4
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 +6 -0
- package/dist/cli/cli.js +13 -0
- package/dist/cli/cli.js.map +1 -1
- package/dist/report/index.js +1 -2
- package/dist/report/index.js.map +1 -1
- package/dist/util/repo.d.ts +1 -0
- package/dist/util/repo.d.ts.map +1 -1
- package/dist/util/repo.js +19 -1
- package/dist/util/repo.js.map +1 -1
- package/package.json +2 -1
- package/.vscode/launch.json +0 -14
- package/bundle/index.js +0 -23
- package/dist/util/archive.d.ts +0 -34
- package/dist/util/archive.d.ts.map +0 -1
- package/dist/util/archive.js +0 -110
- package/dist/util/archive.js.map +0 -1
- package/dist/util/proxy.d.ts +0 -45
- package/dist/util/proxy.d.ts.map +0 -1
- package/dist/util/proxy.js +0 -143
- package/dist/util/proxy.js.map +0 -1
- package/report.png +0 -0
- package/src/bot/lark.ts +0 -184
- package/src/cli/cli.ts +0 -81
- package/src/index.ts +0 -67
- package/src/report/index.ts +0 -50
- package/src/tool/prscan.ts +0 -634
- package/src/util/analyze.ts +0 -248
- package/src/util/memory-archive.ts +0 -184
- package/src/util/npm.ts +0 -100
- package/src/util/parse.ts +0 -103
- package/src/util/repo.ts +0 -224
- package/tsconfig.json +0 -43
package/dist/util/archive.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export interface ExtractOptions {
|
|
2
|
-
/** 解压到的目标目录 */
|
|
3
|
-
targetDir: string;
|
|
4
|
-
/** 文件过滤器,返回true表示解压该文件 */
|
|
5
|
-
filter?: (path: string, entry: any) => boolean;
|
|
6
|
-
/** 是否覆盖已存在的文件 */
|
|
7
|
-
overwrite?: boolean;
|
|
8
|
-
/** 是否创建目标目录 */
|
|
9
|
-
createDir?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export interface ArchiveEntry {
|
|
12
|
-
path: string;
|
|
13
|
-
type: 'file' | 'directory' | 'symlink' | 'other';
|
|
14
|
-
size: number;
|
|
15
|
-
mode: number;
|
|
16
|
-
mtime: Date;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* 解压 .tar.gz 文件
|
|
20
|
-
*/
|
|
21
|
-
export declare function extractTarGz(archivePath: string, options: ExtractOptions): Promise<string[]>;
|
|
22
|
-
/**
|
|
23
|
-
* 列出压缩包内容而不解压
|
|
24
|
-
*/
|
|
25
|
-
export declare function listTarGz(archivePath: string): Promise<ArchiveEntry[]>;
|
|
26
|
-
/**
|
|
27
|
-
* 解压单个文件
|
|
28
|
-
*/
|
|
29
|
-
export declare function extractSingleFile(archivePath: string, filePath: string, targetPath: string): Promise<boolean>;
|
|
30
|
-
/**
|
|
31
|
-
* 解压并过滤特定类型文件
|
|
32
|
-
*/
|
|
33
|
-
export declare function extractFilesByExtension(archivePath: string, targetDir: string, extensions: string[]): Promise<string[]>;
|
|
34
|
-
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/util/archive.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC3B,eAAe;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;IAC/C,iBAAiB;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,YAAY,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoCnB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAiB5E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACnC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CACzC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB"}
|
package/dist/util/archive.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import tar from 'tar';
|
|
2
|
-
import { mkdir, access } from 'fs/promises';
|
|
3
|
-
import { dirname } from 'path';
|
|
4
|
-
/**
|
|
5
|
-
* 解压 .tar.gz 文件
|
|
6
|
-
*/
|
|
7
|
-
export async function extractTarGz(archivePath, options) {
|
|
8
|
-
const { targetDir, filter, overwrite = true, createDir = true } = options;
|
|
9
|
-
// 创建目标目录
|
|
10
|
-
if (createDir) {
|
|
11
|
-
await mkdir(targetDir, { recursive: true });
|
|
12
|
-
}
|
|
13
|
-
// 检查目标目录是否存在
|
|
14
|
-
try {
|
|
15
|
-
await access(targetDir);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
throw new Error(`Target directory does not exist: ${targetDir}`);
|
|
19
|
-
}
|
|
20
|
-
const extractedFiles = [];
|
|
21
|
-
await tar.extract({
|
|
22
|
-
file: archivePath,
|
|
23
|
-
cwd: targetDir,
|
|
24
|
-
filter: filter ? (path, entry) => {
|
|
25
|
-
const shouldExtract = filter(path, entry);
|
|
26
|
-
if (shouldExtract) {
|
|
27
|
-
extractedFiles.push(path);
|
|
28
|
-
}
|
|
29
|
-
return shouldExtract;
|
|
30
|
-
} : undefined,
|
|
31
|
-
newer: !overwrite, // 如果不覆盖,只解压更新的文件
|
|
32
|
-
onentry: (entry) => {
|
|
33
|
-
if (!filter) {
|
|
34
|
-
extractedFiles.push(entry.path);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
return extractedFiles;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* 列出压缩包内容而不解压
|
|
42
|
-
*/
|
|
43
|
-
export async function listTarGz(archivePath) {
|
|
44
|
-
const entries = [];
|
|
45
|
-
await tar.list({
|
|
46
|
-
file: archivePath,
|
|
47
|
-
onentry: (entry) => {
|
|
48
|
-
entries.push({
|
|
49
|
-
path: entry.path,
|
|
50
|
-
type: getEntryType(entry.type),
|
|
51
|
-
size: entry.size || 0,
|
|
52
|
-
mode: entry.mode || 0,
|
|
53
|
-
mtime: entry.mtime || new Date()
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
return entries;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* 解压单个文件
|
|
61
|
-
*/
|
|
62
|
-
export async function extractSingleFile(archivePath, filePath, targetPath) {
|
|
63
|
-
let found = false;
|
|
64
|
-
// 确保目标目录存在
|
|
65
|
-
await mkdir(dirname(targetPath), { recursive: true });
|
|
66
|
-
await tar.extract({
|
|
67
|
-
file: archivePath,
|
|
68
|
-
filter: (path) => {
|
|
69
|
-
if (path === filePath) {
|
|
70
|
-
found = true;
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
},
|
|
75
|
-
strip: 0,
|
|
76
|
-
C: dirname(targetPath),
|
|
77
|
-
transform: {
|
|
78
|
-
[filePath]: targetPath
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
return found;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* 解压并过滤特定类型文件
|
|
85
|
-
*/
|
|
86
|
-
export async function extractFilesByExtension(archivePath, targetDir, extensions) {
|
|
87
|
-
const normalizedExts = extensions.map(ext => ext.startsWith('.') ? ext : `.${ext}`);
|
|
88
|
-
return extractTarGz(archivePath, {
|
|
89
|
-
targetDir,
|
|
90
|
-
filter: (path) => {
|
|
91
|
-
return normalizedExts.some(ext => path.endsWith(ext));
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
function getEntryType(type) {
|
|
96
|
-
switch (type) {
|
|
97
|
-
case 'File':
|
|
98
|
-
case 'file':
|
|
99
|
-
return 'file';
|
|
100
|
-
case 'Directory':
|
|
101
|
-
case 'directory':
|
|
102
|
-
return 'directory';
|
|
103
|
-
case 'SymbolicLink':
|
|
104
|
-
case 'symlink':
|
|
105
|
-
return 'symlink';
|
|
106
|
-
default:
|
|
107
|
-
return 'other';
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=archive.js.map
|
package/dist/util/archive.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/util/archive.ts"],"names":[],"mappings":"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"}
|
package/dist/util/proxy.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export interface ProxyConfig {
|
|
2
|
-
http?: string;
|
|
3
|
-
https?: string;
|
|
4
|
-
noProxy?: string[];
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* 全局代理配置
|
|
8
|
-
*/
|
|
9
|
-
export declare class GlobalProxy {
|
|
10
|
-
private static httpAgent;
|
|
11
|
-
private static httpsAgent;
|
|
12
|
-
private static originalGlobalAgent;
|
|
13
|
-
/**
|
|
14
|
-
* 设置全局代理
|
|
15
|
-
*/
|
|
16
|
-
static setup(config: ProxyConfig): void;
|
|
17
|
-
/**
|
|
18
|
-
* 为fetch请求设置代理
|
|
19
|
-
*/
|
|
20
|
-
static setupFetch(config: ProxyConfig): void;
|
|
21
|
-
/**
|
|
22
|
-
* 检查URL是否应该使用代理
|
|
23
|
-
*/
|
|
24
|
-
private static shouldUseProxy;
|
|
25
|
-
/**
|
|
26
|
-
* 获取代理配置的Agent
|
|
27
|
-
*/
|
|
28
|
-
static getAgents(): {
|
|
29
|
-
httpAgent: any;
|
|
30
|
-
httpsAgent: any;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* 清除代理设置
|
|
34
|
-
*/
|
|
35
|
-
static clear(): void;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 从环境变量读取代理配置
|
|
39
|
-
*/
|
|
40
|
-
export declare function getProxyFromEnv(): ProxyConfig;
|
|
41
|
-
/**
|
|
42
|
-
* 初始化代理设置
|
|
43
|
-
*/
|
|
44
|
-
export declare function initializeProxy(config?: ProxyConfig): void;
|
|
45
|
-
//# sourceMappingURL=proxy.d.ts.map
|
package/dist/util/proxy.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/util/proxy.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAqC;IAC7D,OAAO,CAAC,MAAM,CAAC,UAAU,CAAsC;IAC/D,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAsC;IAExE;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW;IAmChC;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,WAAW;IA6BrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAkB7B;;OAEG;IACH,MAAM,CAAC,SAAS;;;;IAOhB;;OAEG;IACH,MAAM,CAAC,KAAK;CAkBf;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,WAAW,CAM7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW,QAUnD"}
|
package/dist/util/proxy.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Agent as HttpAgent } from 'http';
|
|
2
|
-
import { Agent as HttpsAgent } from 'https';
|
|
3
|
-
import { ProxyAgent } from 'proxy-agent';
|
|
4
|
-
/**
|
|
5
|
-
* 全局代理配置
|
|
6
|
-
*/
|
|
7
|
-
export class GlobalProxy {
|
|
8
|
-
static httpAgent;
|
|
9
|
-
static httpsAgent;
|
|
10
|
-
static originalGlobalAgent;
|
|
11
|
-
/**
|
|
12
|
-
* 设置全局代理
|
|
13
|
-
*/
|
|
14
|
-
static setup(config) {
|
|
15
|
-
// 方法1: 设置环境变量
|
|
16
|
-
if (config.http) {
|
|
17
|
-
process.env.HTTP_PROXY = config.http;
|
|
18
|
-
process.env.http_proxy = config.http;
|
|
19
|
-
}
|
|
20
|
-
if (config.https) {
|
|
21
|
-
process.env.HTTPS_PROXY = config.https;
|
|
22
|
-
process.env.https_proxy = config.https;
|
|
23
|
-
}
|
|
24
|
-
if (config.noProxy) {
|
|
25
|
-
process.env.NO_PROXY = config.noProxy.join(',');
|
|
26
|
-
process.env.no_proxy = config.noProxy.join(',');
|
|
27
|
-
}
|
|
28
|
-
// 方法2: 使用 proxy-agent (推荐)
|
|
29
|
-
if (config.http || config.https) {
|
|
30
|
-
const proxyUrl = config.https || config.http;
|
|
31
|
-
try {
|
|
32
|
-
this.httpAgent = new ProxyAgent(proxyUrl);
|
|
33
|
-
this.httpsAgent = new ProxyAgent(proxyUrl);
|
|
34
|
-
// 设置全局默认agent
|
|
35
|
-
globalThis.httpGlobalAgent = this.httpAgent;
|
|
36
|
-
globalThis.httpsGlobalAgent = this.httpsAgent;
|
|
37
|
-
console.log(`✅ Global proxy set to: ${proxyUrl}`);
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
console.error('❌ Failed to setup proxy agent:', error);
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* 为fetch请求设置代理
|
|
47
|
-
*/
|
|
48
|
-
static setupFetch(config) {
|
|
49
|
-
if (!config.http && !config.https)
|
|
50
|
-
return;
|
|
51
|
-
const proxyUrl = config.https || config.http;
|
|
52
|
-
// 保存原始fetch
|
|
53
|
-
this.originalGlobalAgent = globalThis.fetch;
|
|
54
|
-
// 创建代理agent
|
|
55
|
-
const agent = new ProxyAgent(proxyUrl);
|
|
56
|
-
// 重写全局fetch
|
|
57
|
-
globalThis.fetch = async (input, init) => {
|
|
58
|
-
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
59
|
-
// 检查是否需要代理
|
|
60
|
-
if (this.shouldUseProxy(url, config.noProxy)) {
|
|
61
|
-
const modifiedInit = {
|
|
62
|
-
...init,
|
|
63
|
-
// @ts-ignore
|
|
64
|
-
agent: agent
|
|
65
|
-
};
|
|
66
|
-
return this.originalGlobalAgent(input, modifiedInit);
|
|
67
|
-
}
|
|
68
|
-
return this.originalGlobalAgent(input, init);
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* 检查URL是否应该使用代理
|
|
73
|
-
*/
|
|
74
|
-
static shouldUseProxy(url, noProxy) {
|
|
75
|
-
if (!noProxy || noProxy.length === 0)
|
|
76
|
-
return true;
|
|
77
|
-
try {
|
|
78
|
-
const urlObj = new URL(url);
|
|
79
|
-
const hostname = urlObj.hostname;
|
|
80
|
-
return !noProxy.some(pattern => {
|
|
81
|
-
if (pattern.startsWith('.')) {
|
|
82
|
-
return hostname.endsWith(pattern);
|
|
83
|
-
}
|
|
84
|
-
return hostname === pattern || hostname.endsWith(`.${pattern}`);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* 获取代理配置的Agent
|
|
93
|
-
*/
|
|
94
|
-
static getAgents() {
|
|
95
|
-
return {
|
|
96
|
-
httpAgent: this.httpAgent,
|
|
97
|
-
httpsAgent: this.httpsAgent
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* 清除代理设置
|
|
102
|
-
*/
|
|
103
|
-
static clear() {
|
|
104
|
-
delete process.env.HTTP_PROXY;
|
|
105
|
-
delete process.env.http_proxy;
|
|
106
|
-
delete process.env.HTTPS_PROXY;
|
|
107
|
-
delete process.env.https_proxy;
|
|
108
|
-
delete process.env.NO_PROXY;
|
|
109
|
-
delete process.env.no_proxy;
|
|
110
|
-
if (this.originalGlobalAgent) {
|
|
111
|
-
globalThis.fetch = this.originalGlobalAgent;
|
|
112
|
-
}
|
|
113
|
-
this.httpAgent = undefined;
|
|
114
|
-
this.httpsAgent = undefined;
|
|
115
|
-
this.originalGlobalAgent = undefined;
|
|
116
|
-
console.log('🧹 Proxy settings cleared');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* 从环境变量读取代理配置
|
|
121
|
-
*/
|
|
122
|
-
export function getProxyFromEnv() {
|
|
123
|
-
return {
|
|
124
|
-
http: process.env.HTTP_PROXY || process.env.http_proxy,
|
|
125
|
-
https: process.env.HTTPS_PROXY || process.env.https_proxy,
|
|
126
|
-
noProxy: (process.env.NO_PROXY || process.env.no_proxy)?.split(',')
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 初始化代理设置
|
|
131
|
-
*/
|
|
132
|
-
export function initializeProxy(config) {
|
|
133
|
-
const proxyConfig = config || getProxyFromEnv();
|
|
134
|
-
if (proxyConfig.http || proxyConfig.https) {
|
|
135
|
-
console.log('🔄 Initializing proxy settings...');
|
|
136
|
-
GlobalProxy.setup(proxyConfig);
|
|
137
|
-
GlobalProxy.setupFetch(proxyConfig);
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
console.log('ℹ️ No proxy configuration found');
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=proxy.js.map
|
package/dist/util/proxy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/util/proxy.ts"],"names":[],"mappings":"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"}
|
package/report.png
DELETED
|
Binary file
|
package/src/bot/lark.ts
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
// SDK 使用说明 SDK user guide:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/nodejs-sdk/preparation-before-development
|
|
2
|
-
import http from "http";
|
|
3
|
-
import * as lark from "@larksuiteoapi/node-sdk";
|
|
4
|
-
import { scanPRRisks } from "../tool/prscan.js";
|
|
5
|
-
import { makeReportInMd, md2Img } from "../report/index.js";
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as os from "os";
|
|
8
|
-
import * as path from "path";
|
|
9
|
-
|
|
10
|
-
const encryptKey = process.env.key;
|
|
11
|
-
const verificationToken = process.env.token;
|
|
12
|
-
const appId = process.env.id;
|
|
13
|
-
const appSecret = process.env.secret;
|
|
14
|
-
const bindPath = process.env.path || "/larkbot/event";
|
|
15
|
-
const port = process.env.port || 12345;
|
|
16
|
-
|
|
17
|
-
console.log("Lark Bot starting...");
|
|
18
|
-
console.log("App ID:", appId);
|
|
19
|
-
console.log("App Secret:", appSecret);
|
|
20
|
-
console.log("Encrypt Key:", encryptKey);
|
|
21
|
-
console.log("Verification Token:", verificationToken);
|
|
22
|
-
console.log("Event Path:", bindPath);
|
|
23
|
-
console.log("Listening on Port:", port);
|
|
24
|
-
|
|
25
|
-
const client = new lark.Client({
|
|
26
|
-
appId: appId ?? "",
|
|
27
|
-
appSecret: appSecret ?? "",
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// 注册事件 Register event
|
|
31
|
-
const eventDispatcher = new lark.EventDispatcher({
|
|
32
|
-
logger: console,
|
|
33
|
-
loggerLevel: 5,
|
|
34
|
-
encryptKey: encryptKey ?? "",
|
|
35
|
-
verificationToken: verificationToken ?? "",
|
|
36
|
-
}).register({
|
|
37
|
-
"im.message.receive_v1": async (data) => {
|
|
38
|
-
if (data.message.message_type !== "text") {
|
|
39
|
-
client.im.message.reply({
|
|
40
|
-
path: {
|
|
41
|
-
message_id: data.message.message_id,
|
|
42
|
-
},
|
|
43
|
-
data: {
|
|
44
|
-
content: JSON.stringify({
|
|
45
|
-
text:
|
|
46
|
-
"只支持文本消息,收到消息类型:" +
|
|
47
|
-
data.message.message_type,
|
|
48
|
-
}),
|
|
49
|
-
msg_type: "text",
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
return "success";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const msg = JSON.parse(data.message.content).text as any;
|
|
56
|
-
|
|
57
|
-
// 提取PR链接
|
|
58
|
-
const prRegex =
|
|
59
|
-
/(https:\/\/github\.com\/[^\s\/]+\/[^\s\/]+\/pull\/\d+)/g;
|
|
60
|
-
const prLinks = msg.match(prRegex);
|
|
61
|
-
|
|
62
|
-
if (prLinks == null || prLinks.length === 0) {
|
|
63
|
-
client.im.message.reply({
|
|
64
|
-
path: {
|
|
65
|
-
message_id: data.message.message_id,
|
|
66
|
-
},
|
|
67
|
-
data: {
|
|
68
|
-
content: JSON.stringify({ text: "未提取到PR链接" }),
|
|
69
|
-
msg_type: "text",
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
return "success";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
for (const prLink of prLinks) {
|
|
76
|
-
// 提取owner、repo、pr_number
|
|
77
|
-
const match = prLink.match(
|
|
78
|
-
/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/
|
|
79
|
-
);
|
|
80
|
-
if (match) {
|
|
81
|
-
const owner = match[1];
|
|
82
|
-
const repo = match[2];
|
|
83
|
-
const prNumber = match[3];
|
|
84
|
-
|
|
85
|
-
scanPRRisks(owner, repo, prNumber)
|
|
86
|
-
.then((result) => {
|
|
87
|
-
const report = makeReportInMd(result!);
|
|
88
|
-
|
|
89
|
-
client.im.message.reply({
|
|
90
|
-
path: {
|
|
91
|
-
message_id: data.message.message_id,
|
|
92
|
-
},
|
|
93
|
-
data: {
|
|
94
|
-
content: JSON.stringify({
|
|
95
|
-
zh_cn: {
|
|
96
|
-
title: `PR安全扫描结果 - ${owner}/${repo}#${prNumber}`,
|
|
97
|
-
content: [
|
|
98
|
-
[
|
|
99
|
-
{
|
|
100
|
-
tag: "text",
|
|
101
|
-
text: `摘要: ${report.abstract}\n详细结果见下图:`,
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
tag: "md",
|
|
105
|
-
text: report.report,
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
}),
|
|
111
|
-
msg_type: "post",
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
})
|
|
115
|
-
.catch((error) => {
|
|
116
|
-
client.im.message.reply({
|
|
117
|
-
path: {
|
|
118
|
-
message_id: data.message.message_id,
|
|
119
|
-
},
|
|
120
|
-
data: {
|
|
121
|
-
content: JSON.stringify({
|
|
122
|
-
text: `扫描PR ${prLink} 失败: ${error.message}`,
|
|
123
|
-
}),
|
|
124
|
-
msg_type: "text",
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// console.log(data);
|
|
131
|
-
|
|
132
|
-
// client.im.message.reply({
|
|
133
|
-
// path: {
|
|
134
|
-
// message_id: data.message.message_id,
|
|
135
|
-
// },
|
|
136
|
-
// data: {
|
|
137
|
-
// content: JSON.stringify({"text": "收到消息:" + data.message.text}),
|
|
138
|
-
// msg_type: "text"
|
|
139
|
-
// }
|
|
140
|
-
// });
|
|
141
|
-
return "success";
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const server = http.createServer();
|
|
146
|
-
// 创建路由处理器 Create route handler
|
|
147
|
-
server.on(
|
|
148
|
-
"request",
|
|
149
|
-
lark.adaptDefault(bindPath, eventDispatcher, {
|
|
150
|
-
autoChallenge: true,
|
|
151
|
-
})
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
server.listen(port);
|
|
155
|
-
|
|
156
|
-
function createReadStreamFromBuffer(buffer: Buffer, options = {}) {
|
|
157
|
-
// 在系统临时目录创建文件
|
|
158
|
-
const tempDir = os.tmpdir();
|
|
159
|
-
const tempFile = path.join(
|
|
160
|
-
tempDir,
|
|
161
|
-
`buffer-stream-${Date.now()}-${Math.random().toString(36).substr(2)}`
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
// 同步写入临时文件
|
|
165
|
-
fs.writeFileSync(tempFile, buffer);
|
|
166
|
-
|
|
167
|
-
// 创建 read stream
|
|
168
|
-
const readStream = fs.createReadStream(tempFile, options);
|
|
169
|
-
|
|
170
|
-
// 自动清理临时文件
|
|
171
|
-
const cleanup = () => {
|
|
172
|
-
fs.unlink(tempFile, (err) => {
|
|
173
|
-
if (err && err.code !== "ENOENT") {
|
|
174
|
-
console.error("清理临时文件失败:", err);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
readStream.on("close", cleanup);
|
|
180
|
-
readStream.on("error", cleanup);
|
|
181
|
-
readStream.on("end", cleanup);
|
|
182
|
-
|
|
183
|
-
return readStream;
|
|
184
|
-
}
|
package/src/cli/cli.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { program } from "commander";
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
import { scanByFileDiff, scanPRRisks } from "../tool/prscan.js";
|
|
5
|
-
import { writeFileSync } from "fs";
|
|
6
|
-
import { makeReportInMd } from "../report/index.js";
|
|
7
|
-
program
|
|
8
|
-
.command("branch")
|
|
9
|
-
.description("根据分支文件变更分析NPM依赖变更")
|
|
10
|
-
.argument("<base>", "基础分支")
|
|
11
|
-
.argument("<head>", "变更分支")
|
|
12
|
-
.option("-r, --repo <repo>", "仓库路径", ".")
|
|
13
|
-
.option("-o, --output <output>", "输出文件路径,若不指定则输出到控制台", "")
|
|
14
|
-
.action(async (base: string, head: string, options: { repo: string, output: string }) => {
|
|
15
|
-
console.log(`分析 ${options.repo} 仓库从 ${base} 到 ${head} 的变更`);
|
|
16
|
-
const output = execSync(`git diff --name-only ${base} ${head}`, { cwd: options.repo }).toString();
|
|
17
|
-
const files = [];
|
|
18
|
-
for (let line of output.split("\n")) {
|
|
19
|
-
line = line.trim();
|
|
20
|
-
if (line.endsWith("yarn.lock")) {
|
|
21
|
-
console.log(` 发现变更: ${line}`);
|
|
22
|
-
} else if (line.endsWith("pnpm-lock.yaml")) {
|
|
23
|
-
console.log(` 发现变更: ${line}`);
|
|
24
|
-
} else if (line.endsWith("package-lock.json")) {
|
|
25
|
-
console.error(` 发现变更: ${line} (暂不支持分析package-lock.json)`);
|
|
26
|
-
continue;
|
|
27
|
-
} else {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const file1 = execSync(`git show ${base}:${line}`, { cwd: options.repo }).toString();
|
|
32
|
-
const file2 = execSync(`git show ${head}:${line}`, { cwd: options.repo }).toString();
|
|
33
|
-
files.push({
|
|
34
|
-
filename: line,
|
|
35
|
-
oldContent: file1,
|
|
36
|
-
newContent: file2,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const sr = await scanByFileDiff(files);
|
|
41
|
-
|
|
42
|
-
const report = makeReportInMd(sr);
|
|
43
|
-
if (options.output.length > 0) {
|
|
44
|
-
|
|
45
|
-
writeFileSync(options.output, report.report, { encoding: "utf-8" });
|
|
46
|
-
console.log(`分析报告已写入 ${options.output}`);
|
|
47
|
-
} else {
|
|
48
|
-
console.log(report.report);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
program.command("github").description("根据GitHub Pull Request分析NPM依赖变更")
|
|
53
|
-
.argument("<link>", "Pull Request链接")
|
|
54
|
-
.option("-t, --token <token>", "GitHub访问令牌", "")
|
|
55
|
-
.option("-o, --output <output>", "输出文件路径,若不指定则输出到控制台", "")
|
|
56
|
-
.action(async (link: string, options: { token: string, output: string }) => {
|
|
57
|
-
console.log(`分析 Pull Request: ${link}`);
|
|
58
|
-
|
|
59
|
-
const match = link.match(
|
|
60
|
-
/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/
|
|
61
|
-
);
|
|
62
|
-
if (match) {
|
|
63
|
-
const owner = match[1];
|
|
64
|
-
const repo = match[2];
|
|
65
|
-
const prNumber = match[3];
|
|
66
|
-
|
|
67
|
-
const sr = await scanPRRisks(owner!, repo!, parseInt(prNumber!), options.token);
|
|
68
|
-
const report = makeReportInMd(sr!);
|
|
69
|
-
if (options.output.length > 0) {
|
|
70
|
-
writeFileSync(options.output, report.report, { encoding: "utf-8" });
|
|
71
|
-
console.log(`分析报告已写入 ${options.output}`);
|
|
72
|
-
} else {
|
|
73
|
-
console.log(report.report);
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
console.error("无法解析Pull Request链接");
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
program.parse();
|