@jonathanleelx/meddle 0.3.1 → 0.4.0-beta.10
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/bin/commands/update.js +236 -0
- package/bin/index.js +4 -0
- package/bin/lib/update-check.js +523 -0
- package/dist/helpers.d.ts +13 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +42 -0
- package/dist/helpers.js.map +1 -1
- package/index.js +6 -2
- package/package.json +2 -1
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle update - Check for updates and upgrade meddle
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* meddle update check and upgrade to the latest version
|
|
6
|
+
* meddle update --beta check and upgrade to the latest beta version
|
|
7
|
+
* meddle update --check only check, print the available version
|
|
8
|
+
* meddle update --version <x.y.z> install a specific version
|
|
9
|
+
* meddle update --auto on|off enable/disable auto-update (default off)
|
|
10
|
+
* meddle update status show install method / versions / auto-update
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const os = require('os')
|
|
14
|
+
const path = require('path')
|
|
15
|
+
const { spawnSync } = require('child_process')
|
|
16
|
+
const { resolveMeddleHome } = require('../lib/meddle-home')
|
|
17
|
+
const output = require('../lib/output')
|
|
18
|
+
const {
|
|
19
|
+
compareVersions,
|
|
20
|
+
getLatestVersionNpm,
|
|
21
|
+
getLatestVersionGithub,
|
|
22
|
+
getInstallMethod,
|
|
23
|
+
checkForUpdate,
|
|
24
|
+
downloadBinaryAsset,
|
|
25
|
+
getAutoUpdate,
|
|
26
|
+
setAutoUpdate,
|
|
27
|
+
inferChannel,
|
|
28
|
+
} = require('../lib/update-check')
|
|
29
|
+
|
|
30
|
+
const PACKAGE_NAME = '@jonathanleelx/meddle'
|
|
31
|
+
|
|
32
|
+
const args = process.argv.slice(2)
|
|
33
|
+
const jsonFlag = args.includes('--json')
|
|
34
|
+
output.setJsonMode(jsonFlag)
|
|
35
|
+
|
|
36
|
+
const current = require(path.join(__dirname, '../../package.json')).version
|
|
37
|
+
const home = resolveMeddleHome()
|
|
38
|
+
const installMethod = getInstallMethod({ moduleDir: __dirname })
|
|
39
|
+
|
|
40
|
+
function isNpmInstall() {
|
|
41
|
+
return installMethod === 'npm'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function formatBytes(bytes) {
|
|
45
|
+
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
|
|
46
|
+
if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`
|
|
47
|
+
return `${bytes} B`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const PROGRESS_WIDTH = 40
|
|
51
|
+
|
|
52
|
+
function drawProgressBar({ received, total, attempt, maxAttempts }) {
|
|
53
|
+
const label = attempt > 1 ? ` (第 ${attempt}/${maxAttempts} 次尝试)` : ''
|
|
54
|
+
if (total > 0) {
|
|
55
|
+
const ratio = Math.min(1, received / total)
|
|
56
|
+
const filled = Math.round(PROGRESS_WIDTH * ratio)
|
|
57
|
+
const bar = '#'.repeat(filled) + '-'.repeat(PROGRESS_WIDTH - filled)
|
|
58
|
+
const line = ` [${bar}] ${(ratio * 100).toFixed(1)}% ${formatBytes(received)}/${formatBytes(total)}${label}`
|
|
59
|
+
process.stdout.write(`\r${line}`)
|
|
60
|
+
} else {
|
|
61
|
+
process.stdout.write(`\r 下载中 ${formatBytes(received)}${label}...`)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function showHelp() {
|
|
66
|
+
output.plain(`
|
|
67
|
+
meddle update - 检查并升级 meddle
|
|
68
|
+
|
|
69
|
+
用法:
|
|
70
|
+
meddle update 检查并升级(beta 版本默认走 beta 频道)
|
|
71
|
+
meddle update --beta 切换到 beta 频道并升级到最新 beta 版本
|
|
72
|
+
meddle update --stable 切换到稳定频道并升级到最新稳定版本(可降级)
|
|
73
|
+
meddle update --check 仅检查,提示可用版本 (有新版本时退出码为 2)
|
|
74
|
+
meddle update --check --beta 仅检查 beta 版本
|
|
75
|
+
meddle update --version <x.y.z> 安装指定版本
|
|
76
|
+
meddle update --auto on|off 启用/禁用自动更新 (默认关闭)
|
|
77
|
+
meddle update status 查看安装方式、当前版本和自动更新开关
|
|
78
|
+
meddle update --help, -h 显示帮助
|
|
79
|
+
`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function resolveLatest({ force = false, notify = true, channel = 'stable', explicitChannel = false } = {}) {
|
|
83
|
+
const info = await checkForUpdate({
|
|
84
|
+
home,
|
|
85
|
+
installMethod,
|
|
86
|
+
current,
|
|
87
|
+
force,
|
|
88
|
+
channel,
|
|
89
|
+
explicitChannel,
|
|
90
|
+
})
|
|
91
|
+
if (notify) {
|
|
92
|
+
if (info.outdated) {
|
|
93
|
+
output.info(`发现新版本 ${info.latest} (当前 ${info.current})`)
|
|
94
|
+
} else if (info.latest === info.current) {
|
|
95
|
+
output.success(`已是最新版本 (${info.current})`)
|
|
96
|
+
} else {
|
|
97
|
+
const channelLabel = info.channel === 'beta' ? 'beta' : '稳定'
|
|
98
|
+
output.info(`当前 ${info.current} 已超过${channelLabel}频道最新版本 ${info.latest}`)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return info
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function installVersion(version) {
|
|
105
|
+
if (!isNpmInstall()) {
|
|
106
|
+
const binDir = process.env.MEDDLE_BIN_DIR || path.join(home, 'bin')
|
|
107
|
+
const destFile = path.join(binDir, os.platform() === 'win32' ? 'meddle.exe' : 'meddle')
|
|
108
|
+
output.info(`下载 meddle ${version} (${os.platform()}/${os.arch()})...`)
|
|
109
|
+
let progressShown = false
|
|
110
|
+
const showProgress = output.isJsonMode() ? () => {} : drawProgressBar
|
|
111
|
+
try {
|
|
112
|
+
const result = await downloadBinaryAsset({
|
|
113
|
+
version,
|
|
114
|
+
destFile,
|
|
115
|
+
platform: os.platform(),
|
|
116
|
+
arch: os.arch(),
|
|
117
|
+
onAttempt: (attempt, maxAttempts) => {
|
|
118
|
+
if (attempt > 1) {
|
|
119
|
+
process.stdout.write('\n')
|
|
120
|
+
progressShown = false
|
|
121
|
+
output.info(`连接中断,正在重试 (${attempt}/${maxAttempts})...`)
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
onProgress: (p) => {
|
|
125
|
+
showProgress(p)
|
|
126
|
+
progressShown = true
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
if (progressShown) process.stdout.write('\n')
|
|
130
|
+
output.success(`已安装 meddle ${version} 到 ${result.installed}`)
|
|
131
|
+
if (result.backup) output.info(`旧版本已备份到 ${result.backup}`)
|
|
132
|
+
output.info('重启 meddle 后新版本生效')
|
|
133
|
+
} catch (err) {
|
|
134
|
+
if (progressShown) process.stdout.write('\n')
|
|
135
|
+
output.error(`升级失败: ${err && err.message ? err.message : err}`)
|
|
136
|
+
process.exit(1)
|
|
137
|
+
}
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
output.info(`正在通过 npm 升级 ${PACKAGE_NAME}@${version}...`)
|
|
142
|
+
const child = spawnSync('npm', ['install', '-g', `${PACKAGE_NAME}@${version}`], {
|
|
143
|
+
stdio: 'inherit',
|
|
144
|
+
// On Windows `npm` resolves to npm.cmd which Node cannot spawn directly
|
|
145
|
+
// unless run through a shell (Node >=18.20.2/20.12.2/22.3.0: EINVAL; older: ENOENT).
|
|
146
|
+
shell: os.platform() === 'win32',
|
|
147
|
+
})
|
|
148
|
+
if (child.error) {
|
|
149
|
+
output.error(`npm 升级失败: ${child.error.message}`)
|
|
150
|
+
process.exit(1)
|
|
151
|
+
}
|
|
152
|
+
if (child.status !== 0) {
|
|
153
|
+
output.error(`npm 升级失败 (exit ${child.status})`)
|
|
154
|
+
process.exit(child.status || 1)
|
|
155
|
+
}
|
|
156
|
+
output.success(`已升级到 ${PACKAGE_NAME}@${version}`)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function run() {
|
|
160
|
+
const flag = args.find((a) => a === '--check' || a === 'status' || a === '--help' || a === '-h')
|
|
161
|
+
const versionFlagIndex = args.indexOf('--version')
|
|
162
|
+
const autoFlagIndex = args.indexOf('--auto')
|
|
163
|
+
const explicitChannel = args.includes('--beta') || args.includes('--stable')
|
|
164
|
+
const channel = args.includes('--beta') ? 'beta' : args.includes('--stable') ? 'stable' : inferChannel(current)
|
|
165
|
+
|
|
166
|
+
if (flag === '--help' || flag === '-h') {
|
|
167
|
+
showHelp()
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (flag === 'status') {
|
|
172
|
+
const info = await resolveLatest({ notify: false, channel, explicitChannel })
|
|
173
|
+
output.header('Meddle Update Status')
|
|
174
|
+
output.kv('Install method', installMethod)
|
|
175
|
+
output.kv('Channel', channel)
|
|
176
|
+
output.kv('Current', info.current)
|
|
177
|
+
output.kv('Latest', info.latest)
|
|
178
|
+
output.kv('Auto-update', getAutoUpdate(home) ? 'on' : 'off')
|
|
179
|
+
output.info(info.outdated ? '有新版本可用,运行 meddle update 升级' : '已是最新版本')
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (autoFlagIndex >= 0) {
|
|
184
|
+
const value = args[autoFlagIndex + 1]
|
|
185
|
+
if (value !== 'on' && value !== 'off') {
|
|
186
|
+
output.error('--auto 需要 on 或 off')
|
|
187
|
+
process.exit(1)
|
|
188
|
+
}
|
|
189
|
+
setAutoUpdate(home, value === 'on')
|
|
190
|
+
if (value === 'on' && isNpmInstall()) {
|
|
191
|
+
output.success('自动更新已启用(npm 安装下仅启动时提示,仍需要运行 meddle update 升级)')
|
|
192
|
+
} else {
|
|
193
|
+
output.success(
|
|
194
|
+
`自动更新已${value === 'on' ? '启用' : '关闭'}${value === 'on' ? '(重启 meddle 后生效)' : ''}`,
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (versionFlagIndex >= 0) {
|
|
201
|
+
const version = args[versionFlagIndex + 1]
|
|
202
|
+
if (!version) {
|
|
203
|
+
output.error('--version 需要版本号')
|
|
204
|
+
process.exit(1)
|
|
205
|
+
}
|
|
206
|
+
const currentCompare = (() => {
|
|
207
|
+
try { return compareVersions(version, current) } catch (_) { return null }
|
|
208
|
+
})()
|
|
209
|
+
if (currentCompare === null) {
|
|
210
|
+
output.error(`无效版本号: ${version}`)
|
|
211
|
+
process.exit(1)
|
|
212
|
+
}
|
|
213
|
+
if (currentCompare <= 0) {
|
|
214
|
+
output.info(`当前已是 ${current},无需降级`)
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
await installVersion(version)
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (flag === '--check') {
|
|
222
|
+
const info = await resolveLatest({ channel, explicitChannel })
|
|
223
|
+
if (info.outdated) process.exit(2)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// default: check + upgrade
|
|
228
|
+
const info = await resolveLatest({ channel, explicitChannel })
|
|
229
|
+
if (!info.outdated) return
|
|
230
|
+
await installVersion(info.latest)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
run().catch((err) => {
|
|
234
|
+
output.error(`检查更新失败: ${err && err.message ? err.message : err}`)
|
|
235
|
+
process.exit(1)
|
|
236
|
+
})
|
package/bin/index.js
CHANGED
|
@@ -32,6 +32,7 @@ const commands = {
|
|
|
32
32
|
'url': './commands/url.js',
|
|
33
33
|
'status': './commands/status.js',
|
|
34
34
|
'version': './commands/version.js',
|
|
35
|
+
'update': './commands/update.js',
|
|
35
36
|
'session': './commands/session/index.js',
|
|
36
37
|
'mock': './commands/mock/index.js',
|
|
37
38
|
'route': './commands/route/index.js'
|
|
@@ -77,6 +78,9 @@ Meddle - 开发代理工具
|
|
|
77
78
|
meddle status 查看代理状态
|
|
78
79
|
meddle version 查看版本信息
|
|
79
80
|
meddle --version, -v 查看版本信息 (快捷别名)
|
|
81
|
+
meddle update 检查并升级到最新版本
|
|
82
|
+
meddle update --check 仅检查更新
|
|
83
|
+
meddle update --auto on|off 启用/禁用自动更新 (默认关闭)
|
|
80
84
|
|
|
81
85
|
Session 命令 (多实例隔离,预览功能):
|
|
82
86
|
meddle session create [--name <label>] [--port <port>]
|
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle update-check — version check + update download utilities.
|
|
3
|
+
*
|
|
4
|
+
* Pure JS so it runs unmodified in the npm package and in the deno-compiled
|
|
5
|
+
* binary (bin/ is bundled at compile time). Network is injected via
|
|
6
|
+
* `fetchImpl` so specs can point at local fixtures without touching the
|
|
7
|
+
* real npm registry / GitHub.
|
|
8
|
+
*
|
|
9
|
+
* Version sources:
|
|
10
|
+
* - npm installs → npm registry (https://registry.npmjs.org/@jonathanleeelx/meddle/latest)
|
|
11
|
+
* - binary installs → GitHub releases/latest redirect (same logic as scripts/install-binary.sh)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs')
|
|
15
|
+
const os = require('os')
|
|
16
|
+
const path = require('path')
|
|
17
|
+
const crypto = require('crypto')
|
|
18
|
+
const { resolveMeddleHome } = require('./meddle-home')
|
|
19
|
+
|
|
20
|
+
const PACKAGE_NAME = '@jonathanleelx/meddle'
|
|
21
|
+
const REPO = 'JonathanLee-LX/meddle'
|
|
22
|
+
const DEFAULT_NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`
|
|
23
|
+
const DEFAULT_NPM_BETA_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/beta`
|
|
24
|
+
const DEFAULT_GITHUB_LATEST_URL = `https://github.com/${REPO}/releases/latest`
|
|
25
|
+
const DEFAULT_DOWNLOAD_BASE_URL = `https://github.com/${REPO}/releases/download`
|
|
26
|
+
const DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000
|
|
27
|
+
const DEFAULT_TIMEOUT_MS = 5000
|
|
28
|
+
const DEFAULT_DOWNLOAD_TIMEOUT_MS = 5 * 60 * 1000
|
|
29
|
+
|
|
30
|
+
const VERSION_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse a semver-ish string. Returns { major, minor, patch, prerelease } or
|
|
34
|
+
* null when the input is not a valid version.
|
|
35
|
+
*/
|
|
36
|
+
function parseVersion(value) {
|
|
37
|
+
if (typeof value !== 'string') return null
|
|
38
|
+
const m = VERSION_RE.exec(value.trim())
|
|
39
|
+
if (!m) return null
|
|
40
|
+
return {
|
|
41
|
+
major: Number(m[1]),
|
|
42
|
+
minor: Number(m[2]),
|
|
43
|
+
patch: Number(m[3]),
|
|
44
|
+
prerelease: m[4] ? m[4].split('.') : [],
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {unknown} value
|
|
50
|
+
* @returns {boolean}
|
|
51
|
+
*/
|
|
52
|
+
function isValidVersion(value) {
|
|
53
|
+
return parseVersion(value) !== null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Compare two semver strings. -1 when a < b, 0 when equal, 1 when a > b.
|
|
58
|
+
* Prereleases sort before their release (0.4.0-beta.1 < 0.4.0).
|
|
59
|
+
* @throws {Error} when either argument is not a valid version.
|
|
60
|
+
*/
|
|
61
|
+
function compareVersions(a, b) {
|
|
62
|
+
const va = parseVersion(a)
|
|
63
|
+
const vb = parseVersion(b)
|
|
64
|
+
if (!va) throw new Error(`Invalid version: ${a}`)
|
|
65
|
+
if (!vb) throw new Error(`Invalid version: ${b}`)
|
|
66
|
+
|
|
67
|
+
const partsA = [va.major, va.minor, va.patch]
|
|
68
|
+
const partsB = [vb.major, vb.minor, vb.patch]
|
|
69
|
+
for (let i = 0; i < 3; i++) {
|
|
70
|
+
if (partsA[i] !== partsB[i]) return partsA[i] < partsB[i] ? -1 : 1
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (va.prerelease.length === 0 && vb.prerelease.length === 0) return 0
|
|
74
|
+
if (va.prerelease.length === 0) return 1
|
|
75
|
+
if (vb.prerelease.length === 0) return -1
|
|
76
|
+
|
|
77
|
+
const len = Math.max(va.prerelease.length, vb.prerelease.length)
|
|
78
|
+
for (let i = 0; i < len; i++) {
|
|
79
|
+
const pa = va.prerelease[i]
|
|
80
|
+
const pb = vb.prerelease[i]
|
|
81
|
+
if (pa === undefined) return -1
|
|
82
|
+
if (pb === undefined) return 1
|
|
83
|
+
const na = /^\d+$/.test(pa)
|
|
84
|
+
const nb = /^\d+$/.test(pb)
|
|
85
|
+
if (na && nb) {
|
|
86
|
+
if (Number(pa) !== Number(pb)) return Number(pa) < Number(pb) ? -1 : 1
|
|
87
|
+
} else if (na !== nb) {
|
|
88
|
+
// numeric identifiers always sort below non-numeric ones
|
|
89
|
+
return na ? -1 : 1
|
|
90
|
+
} else if (pa !== pb) {
|
|
91
|
+
return pa < pb ? -1 : 1
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return 0
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Fetch the latest version from the npm registry.
|
|
99
|
+
* @param {{ fetchImpl?: Function, registryUrl?: string, timeoutMs?: number, distTag?: string }} opts
|
|
100
|
+
* @returns {Promise<string>}
|
|
101
|
+
*/
|
|
102
|
+
async function getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs, distTag } = {}) {
|
|
103
|
+
const doFetch = fetchImpl || fetch
|
|
104
|
+
const url = registryUrl
|
|
105
|
+
|| (distTag === 'beta'
|
|
106
|
+
? (process.env.MEDDLE_NPM_BETA_REGISTRY_URL || process.env.MEDDLE_NPM_REGISTRY_URL || DEFAULT_NPM_BETA_URL)
|
|
107
|
+
: (process.env.MEDDLE_NPM_REGISTRY_URL || DEFAULT_NPM_REGISTRY_URL))
|
|
108
|
+
const response = await doFetch(url, { signal: AbortSignal.timeout(timeoutMs || DEFAULT_TIMEOUT_MS) })
|
|
109
|
+
if (!response.ok) throw new Error(`npm registry responded ${response.status}`)
|
|
110
|
+
const data = await response.json()
|
|
111
|
+
const version = data && typeof data.version === 'string' ? data.version : ''
|
|
112
|
+
if (!isValidVersion(version)) throw new Error(`npm registry returned no valid version`)
|
|
113
|
+
return version
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Fetch the latest stable version from the GitHub releases/latest redirect
|
|
118
|
+
* (prereleases are excluded by GitHub). Beta versions resolve through the npm
|
|
119
|
+
* registry `beta` dist-tag instead — see checkForUpdate.
|
|
120
|
+
* @param {{ fetchImpl?: Function, latestUrl?: string, timeoutMs?: number }} opts
|
|
121
|
+
* @returns {Promise<string>}
|
|
122
|
+
*/
|
|
123
|
+
async function getLatestVersionGithub({ fetchImpl, latestUrl, timeoutMs } = {}) {
|
|
124
|
+
const doFetch = fetchImpl || fetch
|
|
125
|
+
const url = latestUrl || process.env.MEDDLE_GITHUB_LATEST_URL || DEFAULT_GITHUB_LATEST_URL
|
|
126
|
+
const response = await doFetch(url, {
|
|
127
|
+
redirect: 'manual',
|
|
128
|
+
signal: AbortSignal.timeout(timeoutMs || DEFAULT_TIMEOUT_MS),
|
|
129
|
+
})
|
|
130
|
+
if (response.status < 300 || response.status >= 400) {
|
|
131
|
+
throw new Error(`GitHub latest release did not redirect (${response.status})`)
|
|
132
|
+
}
|
|
133
|
+
const location = response.headers.get('location') || ''
|
|
134
|
+
const match = /\/tag\/(v?[\d][\w.-]*)$/.exec(location)
|
|
135
|
+
if (!match) throw new Error(`Could not resolve latest release tag`)
|
|
136
|
+
return match[1].replace(/^v/, '')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Detect how meddle was installed.
|
|
141
|
+
* npm → the module lives inside a node_modules directory.
|
|
142
|
+
* binary → deno-compiled binary (bin/ bundled inside the executable).
|
|
143
|
+
* @param {{ moduleDir: string }} opts
|
|
144
|
+
* @returns {'npm' | 'binary'}
|
|
145
|
+
*/
|
|
146
|
+
function getInstallMethod({ moduleDir }) {
|
|
147
|
+
return /[\\/]node_modules[\\/]/.test(moduleDir) ? 'npm' : 'binary'
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {string} home meddle home directory
|
|
152
|
+
* @returns {string} path of the update check cache file
|
|
153
|
+
*/
|
|
154
|
+
function updateCachePath(home) {
|
|
155
|
+
return path.join(home, '.cache', 'update-check.json')
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Infer the update channel from the current version: prerelease versions
|
|
160
|
+
* (e.g. 0.4.0-beta.4) default to the beta channel, releases to stable.
|
|
161
|
+
* @param {string} current
|
|
162
|
+
* @returns {'stable' | 'beta'}
|
|
163
|
+
*/
|
|
164
|
+
function inferChannel(current) {
|
|
165
|
+
return isValidVersion(current) && parseVersion(current).prerelease.length > 0 ? 'beta' : 'stable'
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Decide whether the install should move to `latest`. Explicit channel flags
|
|
170
|
+
* (--beta/--stable) mean "switch channels", so a different channel always
|
|
171
|
+
* triggers the move (even a downgrade); the inferred channel only upgrades.
|
|
172
|
+
* @param {{ latest: string, current: string, channel: string, explicitChannel: boolean }} opts
|
|
173
|
+
* @returns {boolean}
|
|
174
|
+
*/
|
|
175
|
+
function outdatedByChannel({ latest, current, channel, explicitChannel }) {
|
|
176
|
+
if (explicitChannel && channel !== inferChannel(current)) return true
|
|
177
|
+
return compareVersions(latest, current) > 0
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {{ home: string, fetchImpl?: Function, installMethod: string, current: string,
|
|
182
|
+
* now?: number, ttlMs?: number, force?: boolean,
|
|
183
|
+
* registryUrl?: string, latestUrl?: string, timeoutMs?: number,
|
|
184
|
+
* channel?: string, explicitChannel?: boolean }} opts
|
|
185
|
+
* @returns {Promise<{ current: string, latest: string, outdated: boolean, fromCache: boolean, checkedAt: number, channel: string }>}
|
|
186
|
+
*/
|
|
187
|
+
async function checkForUpdate(opts) {
|
|
188
|
+
const {
|
|
189
|
+
home,
|
|
190
|
+
installMethod,
|
|
191
|
+
current,
|
|
192
|
+
now = Date.now(),
|
|
193
|
+
ttlMs = DEFAULT_CACHE_TTL_MS,
|
|
194
|
+
force = false,
|
|
195
|
+
fetchImpl,
|
|
196
|
+
registryUrl,
|
|
197
|
+
latestUrl,
|
|
198
|
+
timeoutMs,
|
|
199
|
+
channel = inferChannel(current),
|
|
200
|
+
explicitChannel = false,
|
|
201
|
+
} = opts
|
|
202
|
+
|
|
203
|
+
const cacheFile = updateCachePath(home)
|
|
204
|
+
let cached = null
|
|
205
|
+
try {
|
|
206
|
+
cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
|
207
|
+
} catch (_) {}
|
|
208
|
+
|
|
209
|
+
if (!force && cached && typeof cached.version === 'string' && typeof cached.checkedAt === 'number'
|
|
210
|
+
&& (cached.channel || 'stable') === channel) {
|
|
211
|
+
if (now - cached.checkedAt < ttlMs) {
|
|
212
|
+
return {
|
|
213
|
+
current,
|
|
214
|
+
latest: cached.version,
|
|
215
|
+
outdated: outdatedByChannel({ latest: cached.version, current, channel, explicitChannel }),
|
|
216
|
+
fromCache: true,
|
|
217
|
+
checkedAt: cached.checkedAt,
|
|
218
|
+
channel,
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Beta channel always resolves via the npm registry `beta` dist-tag — the
|
|
224
|
+
// GitHub releases API is rate-limited (403) for unauthenticated callers.
|
|
225
|
+
// Binary installs still download assets from GitHub, but resolve the
|
|
226
|
+
// version number from npm where it is published in lockstep with releases.
|
|
227
|
+
const latest = channel === 'beta'
|
|
228
|
+
? await getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs, distTag: 'beta' })
|
|
229
|
+
: installMethod === 'binary'
|
|
230
|
+
? await getLatestVersionGithub({ fetchImpl, latestUrl, timeoutMs })
|
|
231
|
+
: await getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs })
|
|
232
|
+
|
|
233
|
+
const checkedAt = now
|
|
234
|
+
try {
|
|
235
|
+
fs.mkdirSync(path.dirname(cacheFile), { recursive: true })
|
|
236
|
+
fs.writeFileSync(cacheFile, JSON.stringify({ version: latest, checkedAt, channel }), 'utf8')
|
|
237
|
+
} catch (_) {}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
current,
|
|
241
|
+
latest,
|
|
242
|
+
outdated: outdatedByChannel({ latest, current, channel, explicitChannel }),
|
|
243
|
+
fromCache: false,
|
|
244
|
+
checkedAt,
|
|
245
|
+
channel,
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Map platform/arch to the GitHub release asset name.
|
|
251
|
+
* @param {{ platform: string, arch: string }} opts
|
|
252
|
+
* @returns {string}
|
|
253
|
+
*/
|
|
254
|
+
function getAssetName({ platform, arch }) {
|
|
255
|
+
let osTag
|
|
256
|
+
switch (platform) {
|
|
257
|
+
case 'linux': osTag = 'linux'; break
|
|
258
|
+
case 'darwin': osTag = 'darwin'; break
|
|
259
|
+
case 'win32': osTag = 'windows'; break
|
|
260
|
+
default: throw new Error(`unsupported platform: ${platform}`)
|
|
261
|
+
}
|
|
262
|
+
let archTag
|
|
263
|
+
switch (arch) {
|
|
264
|
+
case 'x64': case 'amd64': archTag = 'x64'; break
|
|
265
|
+
case 'arm64': case 'aarch64': archTag = 'arm64'; break
|
|
266
|
+
default: throw new Error(`unsupported arch: ${arch}`)
|
|
267
|
+
}
|
|
268
|
+
const ext = platform === 'win32' ? '.exe' : ''
|
|
269
|
+
return `meddle-${osTag}-${archTag}${ext}`
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function sha256Hex(buffer) {
|
|
273
|
+
return crypto.createHash('sha256').update(buffer).digest('hex')
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Download a release binary, verify its SHA256 sidecar and atomically replace
|
|
278
|
+
* the existing binary. The previous binary is kept as `<destFile>.bak`. When
|
|
279
|
+
* the final replace fails the backup is restored and a descriptive error is
|
|
280
|
+
* thrown (Windows commonly fails with EPERM on a running binary).
|
|
281
|
+
*
|
|
282
|
+
* The payload download is retried (default 3 attempts) because binaries are
|
|
283
|
+
* large (100MB+) and flaky connections drop mid-body. Progress is reported
|
|
284
|
+
* via `onProgress` while streaming (received/total bytes), and `onAttempt`
|
|
285
|
+
* fires before each attempt (skipping retries is visible to callers).
|
|
286
|
+
* @param {{ version: string, destFile: string, platform: string, arch: string,
|
|
287
|
+
* baseUrl?: string, fetchImpl?: Function, timeoutMs?: number,
|
|
288
|
+
* retries?: number, retryDelayMs?: number,
|
|
289
|
+
* onProgress?: Function, onAttempt?: Function,
|
|
290
|
+
* fsImpl?: object }} opts
|
|
291
|
+
* @returns {Promise<{ installed: string, backup: string, version: string }>}
|
|
292
|
+
*/
|
|
293
|
+
async function downloadBinaryAsset(opts) {
|
|
294
|
+
const { version, destFile, platform, arch } = opts
|
|
295
|
+
const baseUrl = opts.baseUrl || process.env.MEDDLE_UPDATE_BASE_URL || DEFAULT_DOWNLOAD_BASE_URL
|
|
296
|
+
const doFetch = opts.fetchImpl || fetch
|
|
297
|
+
const fsImpl = opts.fsImpl || fs
|
|
298
|
+
const payloadTimeout = opts.timeoutMs || DEFAULT_DOWNLOAD_TIMEOUT_MS
|
|
299
|
+
const maxRetries = opts.retries === undefined ? 3 : opts.retries
|
|
300
|
+
const retryDelayMs = opts.retryDelayMs === undefined ? 1000 : opts.retryDelayMs
|
|
301
|
+
const onProgress = typeof opts.onProgress === 'function' ? opts.onProgress : () => {}
|
|
302
|
+
const onAttempt = typeof opts.onAttempt === 'function' ? opts.onAttempt : () => {}
|
|
303
|
+
|
|
304
|
+
const asset = getAssetName({ platform, arch })
|
|
305
|
+
const assetUrl = `${baseUrl}/v${version}/${asset}`
|
|
306
|
+
const shaUrl = `${assetUrl}.sha256`
|
|
307
|
+
|
|
308
|
+
// The binary is large (100MB+); the checksum sidecar is tiny. Use a long
|
|
309
|
+
// timeout for the payload and the regular timeout for the metadata fetch.
|
|
310
|
+
const fetchPayload = async () => {
|
|
311
|
+
let lastError = null
|
|
312
|
+
for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
|
|
313
|
+
if (attempt > 1 && retryDelayMs > 0) {
|
|
314
|
+
await new Promise((r) => setTimeout(r, retryDelayMs * (attempt - 1)))
|
|
315
|
+
}
|
|
316
|
+
onAttempt(attempt, maxRetries + 1)
|
|
317
|
+
try {
|
|
318
|
+
const response = await doFetch(assetUrl, { signal: AbortSignal.timeout(payloadTimeout) })
|
|
319
|
+
if (!response.ok) throw new Error(`download failed (${response.status})`)
|
|
320
|
+
const total = Number(response.headers.get('content-length')) || 0
|
|
321
|
+
const chunks = []
|
|
322
|
+
let received = 0
|
|
323
|
+
if (response.body && typeof response.body.getReader === 'function') {
|
|
324
|
+
const reader = response.body.getReader()
|
|
325
|
+
for (;;) {
|
|
326
|
+
const { done, value } = await reader.read()
|
|
327
|
+
if (done) break
|
|
328
|
+
chunks.push(Buffer.from(value))
|
|
329
|
+
received += value.byteLength
|
|
330
|
+
onProgress({ received, total })
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
const buf = Buffer.from(await response.arrayBuffer())
|
|
334
|
+
chunks.push(buf)
|
|
335
|
+
received = buf.length
|
|
336
|
+
onProgress({ received, total })
|
|
337
|
+
}
|
|
338
|
+
return Buffer.concat(chunks)
|
|
339
|
+
} catch (err) {
|
|
340
|
+
lastError = err
|
|
341
|
+
if (attempt > maxRetries) break
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
throw lastError || new Error(`download failed for ${assetUrl}`)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const shaResponse = await doFetch(shaUrl, { signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS) })
|
|
348
|
+
if (!shaResponse.ok) throw new Error(`checksum sidecar missing (${shaResponse.status})`)
|
|
349
|
+
|
|
350
|
+
const payload = await fetchPayload()
|
|
351
|
+
const shaText = await shaResponse.text()
|
|
352
|
+
const expected = shaText.trim().split(/\s+/)[0]
|
|
353
|
+
if (!/^[0-9a-f]{64}$/i.test(expected)) throw new Error(`invalid checksum sidecar`)
|
|
354
|
+
if (sha256Hex(payload) !== expected.toLowerCase()) {
|
|
355
|
+
throw new Error(`checksum mismatch for ${asset}`)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const dir = path.dirname(destFile)
|
|
359
|
+
fsImpl.mkdirSync(dir, { recursive: true })
|
|
360
|
+
|
|
361
|
+
const tmpFile = `${destFile}.tmp-${process.pid}`
|
|
362
|
+
fsImpl.writeFileSync(tmpFile, payload)
|
|
363
|
+
if (platform !== 'win32') fsImpl.chmodSync(tmpFile, 0o755)
|
|
364
|
+
|
|
365
|
+
const backup = `${destFile}.bak`
|
|
366
|
+
try {
|
|
367
|
+
if (fsImpl.existsSync(backup)) fsImpl.unlinkSync(backup)
|
|
368
|
+
if (fsImpl.existsSync(destFile)) fsImpl.renameSync(destFile, backup)
|
|
369
|
+
} catch (_) {}
|
|
370
|
+
try {
|
|
371
|
+
fsImpl.renameSync(tmpFile, destFile)
|
|
372
|
+
} catch (err) {
|
|
373
|
+
try {
|
|
374
|
+
if (fsImpl.existsSync(backup) && !fsImpl.existsSync(destFile)) {
|
|
375
|
+
fsImpl.renameSync(backup, destFile)
|
|
376
|
+
}
|
|
377
|
+
} catch (_) {}
|
|
378
|
+
try { fsImpl.unlinkSync(tmpFile) } catch (_) {}
|
|
379
|
+
const hint = process.platform === 'win32'
|
|
380
|
+
? 'Windows 下无法替换运行中的 meddle.exe,请先停止 meddle 再运行 meddle update'
|
|
381
|
+
: '替换二进制失败,请检查文件权限'
|
|
382
|
+
throw new Error(`${hint}: ${(err && err.code) || (err && err.message) || err}`)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return { installed: destFile, backup: fsImpl.existsSync(backup) ? backup : null, version }
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Read the auto-update setting. Precedence: MEDDLE_AUTO_UPDATE env var
|
|
390
|
+
* (when set) → settings.json `autoUpdate` (default false).
|
|
391
|
+
* @param {string} home
|
|
392
|
+
* @returns {boolean}
|
|
393
|
+
*/
|
|
394
|
+
function getAutoUpdate(home) {
|
|
395
|
+
const env = process.env.MEDDLE_AUTO_UPDATE
|
|
396
|
+
if (env !== undefined && env !== '') {
|
|
397
|
+
return env === '1' || env.toLowerCase() === 'true'
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
const settings = JSON.parse(fs.readFileSync(path.join(home, 'settings.json'), 'utf8'))
|
|
401
|
+
return settings.autoUpdate === true
|
|
402
|
+
} catch (_) {
|
|
403
|
+
return false
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Persist the auto-update setting into settings.json, preserving other keys.
|
|
409
|
+
* @param {string} home
|
|
410
|
+
* @param {boolean} value
|
|
411
|
+
*/
|
|
412
|
+
function setAutoUpdate(home, value) {
|
|
413
|
+
const settingsPath = path.join(home, 'settings.json')
|
|
414
|
+
let settings = {}
|
|
415
|
+
try {
|
|
416
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'))
|
|
417
|
+
} catch (_) {}
|
|
418
|
+
if (!settings || typeof settings !== 'object' || Array.isArray(settings)) settings = {}
|
|
419
|
+
settings.autoUpdate = value === true
|
|
420
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true })
|
|
421
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8')
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function printUpdateNotice(info) {
|
|
425
|
+
const channel = process.env.MEDDLE_UPDATE_SILENT ? undefined : console
|
|
426
|
+
if (!channel) return
|
|
427
|
+
if (info.autoUpdated) {
|
|
428
|
+
channel.log(`\n[meddle] 已自动升级到 ${info.latest}(重启 meddle 后生效)`)
|
|
429
|
+
return
|
|
430
|
+
}
|
|
431
|
+
channel.log(
|
|
432
|
+
`\n[meddle] 发现新版本 ${info.latest}(当前 ${info.current}),运行 "meddle update" 升级`
|
|
433
|
+
)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Fire-and-forget startup check. Never blocks, never throws, never keeps the
|
|
438
|
+
* process alive. When auto-update is enabled (binary installs) the new binary
|
|
439
|
+
* is downloaded and verified on disk — but only when the running executable
|
|
440
|
+
* actually matches the install dir, otherwise the download would land where it
|
|
441
|
+
* can never take effect. npm installs only get a notice.
|
|
442
|
+
* @param {{ home?: string, installMethod?: string, current: string,
|
|
443
|
+
* binDir?: string, execPath?: string, delayMs?: number,
|
|
444
|
+
* fetchImpl?: Function, onOutdated?: Function }} opts
|
|
445
|
+
* @returns {void}
|
|
446
|
+
*/
|
|
447
|
+
function resolveRealPath(p) {
|
|
448
|
+
try { return fs.realpathSync(p) } catch (_) { return path.resolve(p) }
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function isSameBinary(a, b) {
|
|
452
|
+
return resolveRealPath(a) === resolveRealPath(b)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function runAsyncUpdateCheck(opts) {
|
|
456
|
+
const home = opts.home || resolveMeddleHome()
|
|
457
|
+
const installMethod = opts.installMethod || getInstallMethod({ moduleDir: __dirname })
|
|
458
|
+
const binDir = opts.binDir || process.env.MEDDLE_BIN_DIR || path.join(home, 'bin')
|
|
459
|
+
const delayMs = opts.delayMs === undefined ? 1500 : opts.delayMs
|
|
460
|
+
const execPath = opts.execPath || process.execPath
|
|
461
|
+
const exeBase = path.basename(execPath).toLowerCase()
|
|
462
|
+
const isMeddleExecutable = exeBase === 'meddle' || exeBase === 'meddle.exe'
|
|
463
|
+
|
|
464
|
+
const timer = setTimeout(() => {
|
|
465
|
+
;(async () => {
|
|
466
|
+
const info = await checkForUpdate({
|
|
467
|
+
home,
|
|
468
|
+
installMethod,
|
|
469
|
+
current: opts.current,
|
|
470
|
+
fetchImpl: opts.fetchImpl,
|
|
471
|
+
})
|
|
472
|
+
if (!info.outdated) return
|
|
473
|
+
let finalInfo = info
|
|
474
|
+
if (getAutoUpdate(home) && installMethod === 'binary') {
|
|
475
|
+
const destFile = path.join(binDir, os.platform() === 'win32' ? 'meddle.exe' : 'meddle')
|
|
476
|
+
if (isMeddleExecutable && !isSameBinary(destFile, execPath)) {
|
|
477
|
+
finalInfo = {
|
|
478
|
+
...info,
|
|
479
|
+
skipAutoUpdate: '安装路径与当前运行路径不一致,跳过自动更新',
|
|
480
|
+
}
|
|
481
|
+
} else {
|
|
482
|
+
try {
|
|
483
|
+
await downloadBinaryAsset({
|
|
484
|
+
version: info.latest,
|
|
485
|
+
destFile,
|
|
486
|
+
platform: os.platform(),
|
|
487
|
+
arch: os.arch(),
|
|
488
|
+
baseUrl: opts.baseUrl,
|
|
489
|
+
fetchImpl: opts.fetchImpl,
|
|
490
|
+
})
|
|
491
|
+
finalInfo = { ...info, autoUpdated: true, destFile }
|
|
492
|
+
} catch (err) {
|
|
493
|
+
finalInfo = { ...info, autoUpdateFailed: err && err.message ? err.message : String(err) }
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (opts.onOutdated) {
|
|
498
|
+
opts.onOutdated(finalInfo)
|
|
499
|
+
} else {
|
|
500
|
+
printUpdateNotice(finalInfo)
|
|
501
|
+
}
|
|
502
|
+
})().catch(() => {})
|
|
503
|
+
}, delayMs)
|
|
504
|
+
|
|
505
|
+
if (typeof timer.unref === 'function') timer.unref()
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
module.exports = {
|
|
509
|
+
compareVersions,
|
|
510
|
+
isValidVersion,
|
|
511
|
+
parseVersion,
|
|
512
|
+
inferChannel,
|
|
513
|
+
getLatestVersionNpm,
|
|
514
|
+
getLatestVersionGithub,
|
|
515
|
+
getInstallMethod,
|
|
516
|
+
checkForUpdate,
|
|
517
|
+
getAssetName,
|
|
518
|
+
downloadBinaryAsset,
|
|
519
|
+
getAutoUpdate,
|
|
520
|
+
setAutoUpdate,
|
|
521
|
+
runAsyncUpdateCheck,
|
|
522
|
+
DEFAULT_DOWNLOAD_TIMEOUT_MS,
|
|
523
|
+
}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -23,6 +23,19 @@ export declare function routeRulesToLegacyMaps(rules: RouteRuleEntry[]): {
|
|
|
23
23
|
excludeMap: ExcludeMap;
|
|
24
24
|
};
|
|
25
25
|
export declare function getFreePort(): Promise<number>;
|
|
26
|
+
/**
|
|
27
|
+
* Listen on a port, retrying with a fresh free port when the requested one is
|
|
28
|
+
* taken. Unlike a bare `server.listen()`, a port conflict surfaces as a
|
|
29
|
+
* retryable error here instead of an async 'error' event that would escape a
|
|
30
|
+
* try/catch and crash the process via uncaughtException.
|
|
31
|
+
* @returns the port the server actually bound to
|
|
32
|
+
* @throws the last listen error when all attempts fail
|
|
33
|
+
*/
|
|
34
|
+
export declare function listenWithRetry(server: {
|
|
35
|
+
listen(port: number, host: string, cb?: () => void): unknown;
|
|
36
|
+
} & NodeJS.EventEmitter, host: string, port: number, opts?: {
|
|
37
|
+
maxRetries?: number;
|
|
38
|
+
}): Promise<number>;
|
|
26
39
|
export declare const ROUTE_RULES_DIR: string;
|
|
27
40
|
export interface ParseEprcResult {
|
|
28
41
|
rules: RouteRuleEntry[];
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC7C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAElD,+BAA+B;AAC/B,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB;AA2BD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAWvE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAW9G;AAuDD,kDAAkD;AAClD,wBAAgB,oBAAoB,CAChC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,EAAE,GACxB;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAUvD;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAE7F;AAYD,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAC5B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,cAAc,EAAE,GAAG,OAAO,EACtC,UAAU,CAAC,EAAE,UAAU,GACxB,MAAM,GAAG,IAAI,CAKf;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAQ5G;AAKD,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAKnD;AAED,eAAO,MAAM,eAAe,QAAmD,CAAC;AAKhF,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAmDxE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAmCnF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC7C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAElD,+BAA+B;AAC/B,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB;AA2BD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAWvE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAW9G;AAuDD,kDAAkD;AAClD,wBAAgB,oBAAoB,CAChC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,EAAE,GACxB;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAUvD;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAE7F;AAYD,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAC5B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,cAAc,EAAE,GAAG,OAAO,EACtC,UAAU,CAAC,EAAE,UAAU,GACxB,MAAM,GAAG,IAAI,CAKf;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAQ5G;AAKD,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE;IAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;CAAE,GAAG,MAAM,CAAC,YAAY,EAC9F,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAED,eAAO,MAAM,eAAe,QAAmD,CAAC;AAKhF,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAmDxE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAmCnF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
|
package/dist/helpers.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.resolveTargetUrlFromRules = resolveTargetUrlFromRules;
|
|
|
41
41
|
exports.resolveTargetUrl = resolveTargetUrl;
|
|
42
42
|
exports.routeRulesToLegacyMaps = routeRulesToLegacyMaps;
|
|
43
43
|
exports.getFreePort = getFreePort;
|
|
44
|
+
exports.listenWithRetry = listenWithRetry;
|
|
44
45
|
exports.parseEprcWithExclusions = parseEprcWithExclusions;
|
|
45
46
|
exports.parseEprc = parseEprc;
|
|
46
47
|
exports.ruleMapToEprcText = ruleMapToEprcText;
|
|
@@ -193,6 +194,47 @@ async function getFreePort() {
|
|
|
193
194
|
(0, portfinder_1.setHighestPort)(highestPort);
|
|
194
195
|
return (0, portfinder_1.getPortPromise)();
|
|
195
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Listen on a port, retrying with a fresh free port when the requested one is
|
|
199
|
+
* taken. Unlike a bare `server.listen()`, a port conflict surfaces as a
|
|
200
|
+
* retryable error here instead of an async 'error' event that would escape a
|
|
201
|
+
* try/catch and crash the process via uncaughtException.
|
|
202
|
+
* @returns the port the server actually bound to
|
|
203
|
+
* @throws the last listen error when all attempts fail
|
|
204
|
+
*/
|
|
205
|
+
function listenWithRetry(server, host, port, opts = {}) {
|
|
206
|
+
const maxRetries = opts.maxRetries ?? 5;
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
let settled = false;
|
|
209
|
+
const settle = (fn) => {
|
|
210
|
+
if (settled)
|
|
211
|
+
return;
|
|
212
|
+
settled = true;
|
|
213
|
+
fn();
|
|
214
|
+
};
|
|
215
|
+
const attempt = (attemptPort, remaining) => {
|
|
216
|
+
const onListening = () => {
|
|
217
|
+
server.removeListener('error', onError);
|
|
218
|
+
const addr = server.address();
|
|
219
|
+
settle(() => resolve(addr ? addr.port : attemptPort));
|
|
220
|
+
};
|
|
221
|
+
const onError = (err) => {
|
|
222
|
+
server.removeListener('listening', onListening);
|
|
223
|
+
if (err && err.code === 'EADDRINUSE' && remaining > 0) {
|
|
224
|
+
getFreePort()
|
|
225
|
+
.then((nextPort) => attempt(nextPort, remaining - 1))
|
|
226
|
+
.catch((e) => settle(() => reject(e)));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
settle(() => reject(err));
|
|
230
|
+
};
|
|
231
|
+
server.once('error', onError);
|
|
232
|
+
server.once('listening', onListening);
|
|
233
|
+
server.listen(attemptPort, host);
|
|
234
|
+
};
|
|
235
|
+
attempt(port, maxRetries);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
196
238
|
exports.ROUTE_RULES_DIR = path.resolve((0, meddle_home_1.resolveMeddleHome)(), 'route-rules');
|
|
197
239
|
const FILE_PATTERN = /^file:\/\//;
|
|
198
240
|
const LOCAL_FILE_PATTERN = /^[A-Za-z]:\\|^\/|^\\/;
|
package/dist/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,0CAWC;AAED,kCAWC;AAwDD,oDAaC;AAED,8DAEC;AAaD,4CASC;AAGD,wDAQC;AAKD,kCAKC;AAaD,0DAmDC;AAED,8BAEC;AAED,8CAmCC;AAED,sDAQC;AAxSD,2CAAyE;AACzE,2CAA6B;AAC7B,2BAAkC;AAElC,oDAAuD;AAYvD,SAAS,wBAAwB,CAAC,OAAe;IAC7C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,+EAA+E;IAC/E,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACpC,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACrC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC3C,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAClD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,kBAAkB,CAAC;QAClD,CAAC,CAAC,OAAO,CAAC;IACd,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACjE,OAAO,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC;AACnC,CAAC;AAED,SAAgB,eAAe,CAAC,OAAe,EAAE,KAAa;IAC1D,IAAI,wBAAwB,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,+EAA+E;IAC/E,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,kEAAkE;QAClE,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,WAAW,CAAC,SAA+B,EAAE,SAA6B;IACtF,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YACtD,IAAI,IAAI,KAAK,QAAQ;gBAAE,SAAS;YAChC,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB,EAAE,UAAkB;IACtE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAElC,uFAAuF;IACvF,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACtD,IAAI,YAAY,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,KAAM,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,KAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACjF,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YACtD,UAAU,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACJ,UAAU,GAAG,MAAM,GAAG,KAAK,CAAC;QAChC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACnG,UAAU,GAAG,YAAY,CAAC,QAAQ,GAAG,UAAU,CAAC;IACpD,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1C,YAAY,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED,IAAI,YAAY,CAAC,QAAQ,KAAK,GAAG,IAAI,YAAY,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACjE,YAAY,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;IAClD,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;QACpD,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;IAC9C,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClE,IAAI,UAAU,IAAI,YAAY,EAAE,CAAC;QAC7B,YAAY,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;IAClD,CAAC;IAED,OAAO,YAAY,CAAC,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAiC;IAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,kDAAkD;AAClD,SAAgB,oBAAoB,CAChC,GAAW,EACX,KAAuB;IAEvB,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC;YAAE,SAAS;QACnD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAAE,SAAS;QACxE,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACtE,IAAI,WAAW,EAAE,CAAC;YACd,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAClC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAgB,yBAAyB,CAAC,GAAW,EAAE,KAAuB;IAC1E,OAAO,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,CAAC;AACjE,CAAC;AAED,SAAS,6BAA6B,CAAC,GAAW,EAAE,OAAgB,EAAE,UAAuB;IACzF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC;YAAE,SAAS;QAC7C,IAAI,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAAE,SAAS;QAC9E,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,4DAA4D;AAC5D,SAAgB,gBAAgB,CAC5B,GAAW,EACX,UAAsC,EACtC,UAAuB;IAEvB,IAAI,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,OAAO,yBAAyB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,6BAA6B,CAAC,GAAG,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AACtE,CAAC;AAED,iDAAiD;AACjD,SAAgB,sBAAsB,CAAC,KAAuB;IAC1D,MAAM,OAAO,GAAY,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAe,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnD,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QACtC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAEzF,KAAK,UAAU,WAAW;IAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;IACtE,IAAA,wBAAW,EAAC,SAAS,CAAC,CAAC;IACvB,IAAA,2BAAc,EAAC,WAAW,CAAC,CAAC;IAC5B,OAAO,IAAA,2BAAc,GAAE,CAAC;AAC5B,CAAC;AAEY,QAAA,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAA,+BAAiB,GAAE,EAAE,aAAa,CAAC,CAAC;AAEhF,MAAM,YAAY,GAAG,YAAY,CAAC;AAClC,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAQlD,SAAgB,uBAAuB,CAAC,OAAe;IACnD,MAAM,KAAK,GAAqB,EAAE,CAAC;IAEnC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO;QAE5E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QAE7B,kEAAkE;QAClE,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAClC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB;gBAC/C,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,wCAAwC;QAE7E,IAAI,MAAM,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,MAAM,GAAG,SAAS,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;QAE1C,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACpB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACtC,IAAI,UAAkB,CAAC;YACvB,IAAI,YAAY,GAAG,MAAM,CAAC;YAC1B,IAAI,EAAE,EAAE,CAAC;gBACL,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxC,YAAY,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACJ,UAAU,GAAG,IAAI,CAAC;YACtB,CAAC;YAED,KAAK,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,UAAU;gBACnB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,cAAc;aAC7B,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AAC1C,CAAC;AAED,SAAgB,SAAS,CAAC,OAAe;IACrC,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;AACpD,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAgB,EAAE,UAAuB;IACvE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,6EAA6E;IAC7E,MAAM,qBAAqB,GAA8E,EAAE,CAAC;IAE5G,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;QAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACzD,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3D,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE3C,iEAAiE;QACjE,MAAM,WAAW,GAAG,GAAG,QAAQ,MAAM,aAAa,EAAE,CAAC;QAErD,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,qBAAqB,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;QACrF,CAAC;QACD,qBAAqB,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC;SACtC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE;QACnC,IAAI,aAAa,GAAG,MAAM,CAAC;QAC3B,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO,YAAY,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,YAAY,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,aAAa,EAAE,CAAC;IAC1G,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC;AAED,SAAgB,qBAAqB,CAAC,QAAgB;IAClD,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../helpers.ts"],"names":[],"mappings":"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"}
|
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const fs = require('fs')
|
|
|
4
4
|
const path = require('path')
|
|
5
5
|
const { connect } = require('net')
|
|
6
6
|
const { WebSocket, WebSocketServer } = require('ws')
|
|
7
|
-
const { resolveTargetUrl, getFreePort } = require('./dist/helpers')
|
|
7
|
+
const { resolveTargetUrl, getFreePort, listenWithRetry } = require('./dist/helpers')
|
|
8
8
|
const { crtMgr, ensureRootCA, getRootCAPath } = require('./dist/cert')
|
|
9
9
|
const { decideRoute } = require('./dist/core/route-decision')
|
|
10
10
|
const { sendShortResponse } = require('./dist/core/short-response')
|
|
@@ -21,6 +21,7 @@ const {
|
|
|
21
21
|
pluginClientIdentity,
|
|
22
22
|
} = require('./dist/core/client-identity')
|
|
23
23
|
const { createApplicationIdentityResolver } = require('./dist/core/application-identity')
|
|
24
|
+
const { runAsyncUpdateCheck } = require('./bin/lib/update-check')
|
|
24
25
|
const {
|
|
25
26
|
authorizeProxyClient,
|
|
26
27
|
buildRemoteAccessConfig,
|
|
@@ -493,6 +494,8 @@ localWSServer.on('connection', (client, req) => {})
|
|
|
493
494
|
|
|
494
495
|
// ===== 启动 =====
|
|
495
496
|
;(async () => {
|
|
497
|
+
// 非阻塞异步版本检查:不会阻塞启动,失败静默,1.5s 后发起且 timer unref
|
|
498
|
+
runAsyncUpdateCheck({ current: require('./package.json').version })
|
|
496
499
|
await ensureRootCA()
|
|
497
500
|
await pluginBoot.bootstrapBuiltinPlugins()
|
|
498
501
|
const port = await getFreePort()
|
|
@@ -868,7 +871,8 @@ proxyServer.on('connect', async (req, socket, head) => {
|
|
|
868
871
|
if (!server) {
|
|
869
872
|
const port = await getFreePort()
|
|
870
873
|
server = await createHttpsServerByCert()
|
|
871
|
-
server
|
|
874
|
+
const boundPort = await listenWithRetry(server, '127.0.0.1', port)
|
|
875
|
+
proxyDebug('listening on ' + boundPort)
|
|
872
876
|
ctx.httpsServerMap.set(originHost, server)
|
|
873
877
|
} else {
|
|
874
878
|
markMitmServerUsed(server)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jonathanleelx/meddle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-beta.10",
|
|
4
4
|
"description": "A simple development proxy server with custom routing rules, mock responses, HTTPS interception, and a plugin system",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "index.js",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"test:identity": "pnpm run build && node scripts/application-identity-smoke.js",
|
|
21
21
|
"test:e2e": "npm run build:web && npm run build && node tests/e2e/interactions.e2e.cjs",
|
|
22
22
|
"test:e2e:rule-drag": "npm run build:web && npm run build && node tests/e2e/rule-drag.e2e.cjs",
|
|
23
|
+
"test:e2e:update": "node tests/e2e/update.e2e.cjs",
|
|
23
24
|
"test:watch": "vitest",
|
|
24
25
|
"test:refactor": "npm run build && node -c index.js && npm test",
|
|
25
26
|
"bench:logs": "node scripts/log-performance-benchmark.js",
|