@jonathanleelx/meddle 0.4.0-beta.3 → 0.4.0-beta.6

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.
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Usage:
5
5
  * meddle update check and upgrade to the latest version
6
+ * meddle update --beta check and upgrade to the latest beta version
6
7
  * meddle update --check only check, print the available version
7
8
  * meddle update --version <x.y.z> install a specific version
8
9
  * meddle update --auto on|off enable/disable auto-update (default off)
@@ -23,6 +24,7 @@ const {
23
24
  downloadBinaryAsset,
24
25
  getAutoUpdate,
25
26
  setAutoUpdate,
27
+ inferChannel,
26
28
  } = require('../lib/update-check')
27
29
 
28
30
  const PACKAGE_NAME = '@jonathanleelx/meddle'
@@ -44,8 +46,11 @@ function showHelp() {
44
46
  meddle update - 检查并升级 meddle
45
47
 
46
48
  用法:
47
- meddle update 检查并升级到最新版本
49
+ meddle update 检查并升级(beta 版本默认走 beta 频道)
50
+ meddle update --beta 强制使用 beta 测试频道
51
+ meddle update --stable 强制使用稳定频道
48
52
  meddle update --check 仅检查,提示可用版本 (有新版本时退出码为 2)
53
+ meddle update --check --beta 仅检查 beta 版本
49
54
  meddle update --version <x.y.z> 安装指定版本
50
55
  meddle update --auto on|off 启用/禁用自动更新 (默认关闭)
51
56
  meddle update status 查看安装方式、当前版本和自动更新开关
@@ -53,12 +58,13 @@ meddle update - 检查并升级 meddle
53
58
  `)
54
59
  }
55
60
 
56
- async function resolveLatest({ force = false, notify = true } = {}) {
61
+ async function resolveLatest({ force = false, notify = true, channel = 'stable' } = {}) {
57
62
  const info = await checkForUpdate({
58
63
  home,
59
64
  installMethod,
60
65
  current,
61
66
  force,
67
+ channel,
62
68
  })
63
69
  if (notify) {
64
70
  if (info.outdated) {
@@ -114,6 +120,7 @@ async function run() {
114
120
  const flag = args.find((a) => a === '--check' || a === 'status' || a === '--help' || a === '-h')
115
121
  const versionFlagIndex = args.indexOf('--version')
116
122
  const autoFlagIndex = args.indexOf('--auto')
123
+ const channel = args.includes('--beta') ? 'beta' : args.includes('--stable') ? 'stable' : inferChannel(current)
117
124
 
118
125
  if (flag === '--help' || flag === '-h') {
119
126
  showHelp()
@@ -121,9 +128,10 @@ async function run() {
121
128
  }
122
129
 
123
130
  if (flag === 'status') {
124
- const info = await resolveLatest({ notify: false })
131
+ const info = await resolveLatest({ notify: false, channel })
125
132
  output.header('Meddle Update Status')
126
133
  output.kv('Install method', installMethod)
134
+ output.kv('Channel', channel)
127
135
  output.kv('Current', info.current)
128
136
  output.kv('Latest', info.latest)
129
137
  output.kv('Auto-update', getAutoUpdate(home) ? 'on' : 'off')
@@ -170,13 +178,13 @@ async function run() {
170
178
  }
171
179
 
172
180
  if (flag === '--check') {
173
- const info = await resolveLatest()
181
+ const info = await resolveLatest({ channel })
174
182
  if (info.outdated) process.exit(2)
175
183
  return
176
184
  }
177
185
 
178
186
  // default: check + upgrade
179
- const info = await resolveLatest()
187
+ const info = await resolveLatest({ channel })
180
188
  if (!info.outdated) return
181
189
  await installVersion(info.latest)
182
190
  }
@@ -20,6 +20,7 @@ const { resolveMeddleHome } = require('./meddle-home')
20
20
  const PACKAGE_NAME = '@jonathanleelx/meddle'
21
21
  const REPO = 'JonathanLee-LX/meddle'
22
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`
23
24
  const DEFAULT_GITHUB_LATEST_URL = `https://github.com/${REPO}/releases/latest`
24
25
  const DEFAULT_DOWNLOAD_BASE_URL = `https://github.com/${REPO}/releases/download`
25
26
  const DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000
@@ -95,12 +96,15 @@ function compareVersions(a, b) {
95
96
 
96
97
  /**
97
98
  * Fetch the latest version from the npm registry.
98
- * @param {{ fetchImpl?: Function, registryUrl?: string, timeoutMs?: number }} opts
99
+ * @param {{ fetchImpl?: Function, registryUrl?: string, timeoutMs?: number, distTag?: string }} opts
99
100
  * @returns {Promise<string>}
100
101
  */
101
- async function getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs } = {}) {
102
+ async function getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs, distTag } = {}) {
102
103
  const doFetch = fetchImpl || fetch
103
- const url = registryUrl || process.env.MEDDLE_NPM_REGISTRY_URL || DEFAULT_NPM_REGISTRY_URL
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))
104
108
  const response = await doFetch(url, { signal: AbortSignal.timeout(timeoutMs || DEFAULT_TIMEOUT_MS) })
105
109
  if (!response.ok) throw new Error(`npm registry responded ${response.status}`)
106
110
  const data = await response.json()
@@ -110,7 +114,9 @@ async function getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs } = {}) {
110
114
  }
111
115
 
112
116
  /**
113
- * Fetch the latest version from the GitHub releases/latest redirect.
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.
114
120
  * @param {{ fetchImpl?: Function, latestUrl?: string, timeoutMs?: number }} opts
115
121
  * @returns {Promise<string>}
116
122
  */
@@ -149,11 +155,22 @@ function updateCachePath(home) {
149
155
  return path.join(home, '.cache', 'update-check.json')
150
156
  }
151
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
+
152
168
  /**
153
169
  * @param {{ home: string, fetchImpl?: Function, installMethod: string, current: string,
154
170
  * now?: number, ttlMs?: number, force?: boolean,
155
- * registryUrl?: string, latestUrl?: string, timeoutMs?: number }} opts
156
- * @returns {Promise<{ current: string, latest: string, outdated: boolean, fromCache: boolean, checkedAt: number }>}
171
+ * registryUrl?: string, latestUrl?: string, timeoutMs?: number,
172
+ * channel?: string }} opts
173
+ * @returns {Promise<{ current: string, latest: string, outdated: boolean, fromCache: boolean, checkedAt: number, channel: string }>}
157
174
  */
158
175
  async function checkForUpdate(opts) {
159
176
  const {
@@ -167,6 +184,7 @@ async function checkForUpdate(opts) {
167
184
  registryUrl,
168
185
  latestUrl,
169
186
  timeoutMs,
187
+ channel = inferChannel(current),
170
188
  } = opts
171
189
 
172
190
  const cacheFile = updateCachePath(home)
@@ -175,7 +193,8 @@ async function checkForUpdate(opts) {
175
193
  cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
176
194
  } catch (_) {}
177
195
 
178
- if (!force && cached && typeof cached.version === 'string' && typeof cached.checkedAt === 'number') {
196
+ if (!force && cached && typeof cached.version === 'string' && typeof cached.checkedAt === 'number'
197
+ && (cached.channel || 'stable') === channel) {
179
198
  if (now - cached.checkedAt < ttlMs) {
180
199
  return {
181
200
  current,
@@ -183,18 +202,25 @@ async function checkForUpdate(opts) {
183
202
  outdated: compareVersions(cached.version, current) > 0,
184
203
  fromCache: true,
185
204
  checkedAt: cached.checkedAt,
205
+ channel,
186
206
  }
187
207
  }
188
208
  }
189
209
 
190
- const latest = installMethod === 'binary'
191
- ? await getLatestVersionGithub({ fetchImpl, latestUrl, timeoutMs })
192
- : await getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs })
210
+ // Beta channel always resolves via the npm registry `beta` dist-tag — the
211
+ // GitHub releases API is rate-limited (403) for unauthenticated callers.
212
+ // Binary installs still download assets from GitHub, but resolve the
213
+ // version number from npm where it is published in lockstep with releases.
214
+ const latest = channel === 'beta'
215
+ ? await getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs, distTag: 'beta' })
216
+ : installMethod === 'binary'
217
+ ? await getLatestVersionGithub({ fetchImpl, latestUrl, timeoutMs })
218
+ : await getLatestVersionNpm({ fetchImpl, registryUrl, timeoutMs })
193
219
 
194
220
  const checkedAt = now
195
221
  try {
196
222
  fs.mkdirSync(path.dirname(cacheFile), { recursive: true })
197
- fs.writeFileSync(cacheFile, JSON.stringify({ version: latest, checkedAt }), 'utf8')
223
+ fs.writeFileSync(cacheFile, JSON.stringify({ version: latest, checkedAt, channel }), 'utf8')
198
224
  } catch (_) {}
199
225
 
200
226
  return {
@@ -203,6 +229,7 @@ async function checkForUpdate(opts) {
203
229
  outdated: compareVersions(latest, current) > 0,
204
230
  fromCache: false,
205
231
  checkedAt,
232
+ channel,
206
233
  }
207
234
  }
208
235
 
@@ -425,6 +452,7 @@ module.exports = {
425
452
  compareVersions,
426
453
  isValidVersion,
427
454
  parseVersion,
455
+ inferChannel,
428
456
  getLatestVersionNpm,
429
457
  getLatestVersionGithub,
430
458
  getInstallMethod,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jonathanleelx/meddle",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0-beta.6",
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",