fix(ime): actually ship @xterm/xterm 6.1.0-beta.304 (v1.0.21 built from stale node_modules with 6.0.0); add predist dependency-consistency gate (scripts/verify-deps.cjs) and rename-retry shim for the AV scan EPERM race
This commit is contained in:
1 parent
ac43844f8a
commit
40336d014d
9 files changed
+128
-4
No files matched your search
@@ -0,0 +1,59 @@
|
||||
/* Dependency consistency gate: node_modules must match package-lock.json.
|
||||
|
||||
Usage: node scripts/verify-deps.cjs (runs first in `predist`)
|
||||
|
||||
Why it exists: v1.0.21 shipped an input-method fix that never reached the
|
||||
build. @xterm/xterm had been pinned to 6.1.0-beta.304 in package.json, but
|
||||
node_modules still held 6.0.0 from an older install — `npm install
|
||||
--package-lock-only` (the last step of predist) rewrites only the lockfile,
|
||||
so the lockfile agreed with package.json while the tree on disk stayed
|
||||
stale, and the bundler took the stale tree. An install that never happened
|
||||
is invisible to every other check, so it gets its own gate here.
|
||||
|
||||
Scope: version equality only, for every entry the lockfile lists under
|
||||
node_modules. The root entry ("") is deliberately excluded — bumping
|
||||
package.json makes the lockfile root version lag by design until the
|
||||
`npm install --package-lock-only` at the end of predist rewrites it. */
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const ROOT = path.join(__dirname, '..')
|
||||
const lock = JSON.parse(fs.readFileSync(path.join(ROOT, 'package-lock.json'), 'utf8'))
|
||||
const packages = lock.packages ?? {}
|
||||
|
||||
const mismatched = []
|
||||
let checked = 0
|
||||
// Optional entries are the cross-platform variants (darwin/linux/arm64 …) that
|
||||
// npm records in the lockfile but never installs on this machine. Their absence
|
||||
// is expected, not drift.
|
||||
let skippedOptional = 0
|
||||
|
||||
for (const [key, entry] of Object.entries(packages)) {
|
||||
if (key === '' || !key.startsWith('node_modules/')) continue
|
||||
// The key is the path under node_modules, so it also resolves nested
|
||||
// ("node_modules/a/node_modules/b") and scoped ("node_modules/@scope/pkg")
|
||||
// entries without any name reconstruction.
|
||||
let installed
|
||||
try {
|
||||
installed = JSON.parse(fs.readFileSync(path.join(ROOT, key, 'package.json'), 'utf8')).version
|
||||
} catch {
|
||||
installed = undefined
|
||||
}
|
||||
if (installed === undefined) {
|
||||
if (entry.optional) skippedOptional++
|
||||
else mismatched.push([key, entry.version, 'MISSING'])
|
||||
continue
|
||||
}
|
||||
checked++
|
||||
if (installed !== entry.version) mismatched.push([key, entry.version, installed])
|
||||
}
|
||||
|
||||
if (mismatched.length) {
|
||||
console.error('node_modules does not match package-lock.json:')
|
||||
for (const [name, expected, actual] of mismatched) {
|
||||
console.error(` ${name}: lockfile expects ${expected}, installed ${actual}`)
|
||||
}
|
||||
console.error('\nnode_modules 与 package-lock.json 不一致,请运行 npm ci 重装依赖')
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`dependencies ok: ${checked} packages verified, ${skippedOptional} optional entries skipped`)
|
||||
Reference in new issue
Block a user