@swimmingliu/autovpn 1.4.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 +102 -0
- package/bin/autovpn.mjs +5 -0
- package/dist/artifacts/list.js +99 -0
- package/dist/artifacts/preview.js +85 -0
- package/dist/backend/node-backend.js +194 -0
- package/dist/backend/python-backend.js +242 -0
- package/dist/backend/select-backend.js +12 -0
- package/dist/backend/types.js +1 -0
- package/dist/cli/commands/index.js +143 -0
- package/dist/cli/errors.js +7 -0
- package/dist/cli/global-options.js +29 -0
- package/dist/cli/main.js +231 -0
- package/dist/cli/native-commands.js +215 -0
- package/dist/cli/output.js +31 -0
- package/dist/config/profile.js +80 -0
- package/dist/doctor/checks.js +184 -0
- package/dist/events/schema.js +45 -0
- package/dist/jobs/commands.js +159 -0
- package/dist/jobs/logs.js +48 -0
- package/dist/jobs/process.js +75 -0
- package/dist/jobs/read.js +282 -0
- package/dist/jobs/store.js +115 -0
- package/dist/pipeline/availability.js +679 -0
- package/dist/pipeline/dedupe.js +104 -0
- package/dist/pipeline/deploy.js +1103 -0
- package/dist/pipeline/extract.js +259 -0
- package/dist/pipeline/obfuscate.js +203 -0
- package/dist/pipeline/orchestrator.js +1014 -0
- package/dist/pipeline/postprocess.js +214 -0
- package/dist/pipeline/proxy-runtime.js +228 -0
- package/dist/pipeline/render.js +91 -0
- package/dist/pipeline/speedtest.js +579 -0
- package/dist/runtime/env.js +35 -0
- package/dist/runtime/paths.js +66 -0
- package/dist/runtime/redaction.js +56 -0
- package/lib/cache.mjs +14 -0
- package/lib/errors.mjs +11 -0
- package/lib/install-python-cli.mjs +63 -0
- package/lib/runner.mjs +113 -0
- package/package.json +39 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { spawn as defaultSpawn } from 'node:child_process';
|
|
3
|
+
import { mergeProjectEnv } from '../runtime/env.js';
|
|
4
|
+
const PYTHON_DEDUPE_HELPER = `
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from vpn_automation.pipeline.dedupe import dedupe_vmess_links
|
|
8
|
+
|
|
9
|
+
payload = json.load(sys.stdin)
|
|
10
|
+
json.dump(dedupe_vmess_links(payload["links"]), sys.stdout, ensure_ascii=False)
|
|
11
|
+
sys.stdout.write("\\n")
|
|
12
|
+
`;
|
|
13
|
+
export function parseVmessLink(link) {
|
|
14
|
+
const encoded = link.replace(/^vmess:\/\//, '');
|
|
15
|
+
const padded = encoded + '='.repeat((4 - (encoded.length % 4)) % 4);
|
|
16
|
+
return JSON.parse(Buffer.from(padded, 'base64url').toString('utf8'));
|
|
17
|
+
}
|
|
18
|
+
export function canonicalVmessKey(payload) {
|
|
19
|
+
return JSON.stringify([
|
|
20
|
+
payload.add ?? '',
|
|
21
|
+
payload.port ?? '',
|
|
22
|
+
payload.id ?? '',
|
|
23
|
+
payload.net ?? '',
|
|
24
|
+
payload.host ?? '',
|
|
25
|
+
payload.path ?? '',
|
|
26
|
+
payload.tls ?? '',
|
|
27
|
+
payload.sni ?? ''
|
|
28
|
+
].map((value) => String(value)));
|
|
29
|
+
}
|
|
30
|
+
export function dedupeVmessLinks(links) {
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
const result = [];
|
|
33
|
+
for (const link of links) {
|
|
34
|
+
const key = canonicalVmessKey(parseVmessLink(link));
|
|
35
|
+
if (seen.has(key)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
seen.add(key);
|
|
39
|
+
result.push(link);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
export function selectPipelineStageBackend(stage, env = process.env) {
|
|
44
|
+
const stageKey = `AUTOVPN_STAGE_BACKEND_${stage.toUpperCase()}`;
|
|
45
|
+
const stageOverride = String(env[stageKey] ?? '').trim().toLowerCase();
|
|
46
|
+
const pipelineOverride = String(env.AUTOVPN_PIPELINE_BACKEND ?? '').trim().toLowerCase();
|
|
47
|
+
const selected = stageOverride || pipelineOverride || 'node';
|
|
48
|
+
return selected === 'python' ? 'python' : 'node';
|
|
49
|
+
}
|
|
50
|
+
async function defaultResolvePythonCli(env) {
|
|
51
|
+
// @ts-expect-error Phase 1 runner remains plain ESM JavaScript.
|
|
52
|
+
const runner = await import('../../lib/runner.mjs');
|
|
53
|
+
return runner.resolveOrInstallPythonCli({ env });
|
|
54
|
+
}
|
|
55
|
+
function pythonCommandFor(resolved) {
|
|
56
|
+
const command = resolved.command;
|
|
57
|
+
const name = path.basename(command).toLowerCase();
|
|
58
|
+
if (['autovpn', 'autovpn.exe'].includes(name)) {
|
|
59
|
+
const executable = process.platform === 'win32' ? 'python.exe' : 'python';
|
|
60
|
+
return path.join(path.dirname(command), executable);
|
|
61
|
+
}
|
|
62
|
+
return process.platform === 'win32' ? 'python.exe' : 'python3';
|
|
63
|
+
}
|
|
64
|
+
async function dedupeVmessLinksWithPython(links, options) {
|
|
65
|
+
const env = mergeProjectEnv(options.cwd ?? process.cwd(), options.env ?? process.env);
|
|
66
|
+
const resolved = options.resolvePythonCli ? await options.resolvePythonCli() : await defaultResolvePythonCli(env);
|
|
67
|
+
const child = (options.spawn ?? defaultSpawn)(pythonCommandFor(resolved), ['-c', PYTHON_DEDUPE_HELPER], {
|
|
68
|
+
cwd: options.cwd ?? process.cwd(),
|
|
69
|
+
env,
|
|
70
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
71
|
+
});
|
|
72
|
+
let stdout = '';
|
|
73
|
+
let stderr = '';
|
|
74
|
+
child.stdout?.on('data', (chunk) => {
|
|
75
|
+
stdout += String(chunk);
|
|
76
|
+
});
|
|
77
|
+
child.stderr?.on('data', (chunk) => {
|
|
78
|
+
stderr += String(chunk);
|
|
79
|
+
});
|
|
80
|
+
const completion = new Promise((resolve, reject) => {
|
|
81
|
+
child.on('error', reject);
|
|
82
|
+
child.on('close', (code) => {
|
|
83
|
+
if (code !== 0) {
|
|
84
|
+
reject(new Error(`Python dedupe backend failed with exit code ${code}: ${stderr.trim()}`));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
resolve(JSON.parse(stdout));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
reject(new Error(`Python dedupe backend returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`));
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
child.stdin?.write(JSON.stringify({ links }));
|
|
96
|
+
child.stdin?.end();
|
|
97
|
+
return completion;
|
|
98
|
+
}
|
|
99
|
+
export async function dedupeVmessLinksWithBackend(links, options = {}) {
|
|
100
|
+
if (selectPipelineStageBackend('dedupe', options.env ?? process.env) === 'python') {
|
|
101
|
+
return options.pythonDedupe ? options.pythonDedupe(links) : dedupeVmessLinksWithPython(links, options);
|
|
102
|
+
}
|
|
103
|
+
return dedupeVmessLinks(links);
|
|
104
|
+
}
|