fix(dev): bootstrap embedded web dependencies

This commit is contained in:
elky
2026-09-04 12:03:57 +08:00
parent 313a637982
commit 4e47c00154
2 changed files with 62 additions and 3 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sync:vscodex": "npm --prefix ../aether-vscodex/web run build && node scripts/sync-vscodex.mjs",
"sync:vscodex": "node scripts/sync-vscodex.mjs",
"predev": "npm run sync:vscodex",
"dev": "vite --host",
"prebuild": "npm run sync:vscodex",
+61 -2
View File
@@ -1,10 +1,69 @@
import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'
import { spawnSync } from 'node:child_process'
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const frontendRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const moduleRoot = resolve(frontendRoot, '..', 'aether-vscodex')
const vueBuild = resolve(moduleRoot, 'web', 'dist')
const webRoot = resolve(moduleRoot, 'web')
const webPackagePath = resolve(webRoot, 'package.json')
const webLockPath = resolve(webRoot, 'package-lock.json')
const webPackage = JSON.parse(readFileSync(webPackagePath, 'utf8'))
const webLock = JSON.parse(readFileSync(webLockPath, 'utf8'))
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const requiredPackages = Object.keys({
...webPackage.dependencies,
...webPackage.devDependencies
})
const requiredCommands = ['vite', 'vue-tsc']
const commandSuffix = process.platform === 'win32' ? '.cmd' : ''
function dependencyMatchesLock(dependency) {
const installedPackagePath = resolve(
webRoot,
'node_modules',
...dependency.split('/'),
'package.json'
)
if (!existsSync(installedPackagePath)) {
return false
}
const lockedVersion = webLock.packages?.[`node_modules/${dependency}`]?.version
const installedVersion = JSON.parse(readFileSync(installedPackagePath, 'utf8')).version
return typeof lockedVersion === 'string' && installedVersion === lockedVersion
}
const hasWebDependencies =
requiredPackages.every(dependencyMatchesLock) &&
requiredCommands.every((command) =>
existsSync(resolve(webRoot, 'node_modules', '.bin', `${command}${commandSuffix}`))
)
function runNpm(args, action) {
const result = spawnSync(npmCommand, ['--prefix', webRoot, ...args], {
stdio: 'inherit'
})
if (result.error) {
throw new Error(`Failed to ${action}: ${result.error.message}`)
}
if (result.status !== 0) {
throw new Error(`${action} failed with exit status ${result.status ?? 'unknown'}`)
}
}
if (!hasWebDependencies) {
console.log('=> aether-vscodex Web dependencies are missing; installing from package-lock.json...')
runNpm(
['ci', '--include=dev', '--no-audit', '--no-fund'],
'install aether-vscodex Web dependencies'
)
}
runNpm(['run', 'build'], 'build aether-vscodex Web')
const vueBuild = resolve(webRoot, 'dist')
const destination = resolve(frontendRoot, 'public', 'aether-vscodex')
if (!existsSync(resolve(vueBuild, 'index.html'))) {