@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.
@@ -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[];
@@ -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]:\\|^\/|^\\/;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../helpers.ts"],"names":[],"mappings":"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"}
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.listen(port, '127.0.0.1', () => { proxyDebug('listening on ' + port) })
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.1",
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",