mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-08-01 20:15:49 +00:00
157 lines
4.7 KiB
JavaScript
157 lines
4.7 KiB
JavaScript
/**
|
||
* Core 构建前将插件真实页面替换为桥接页,构建后还原。
|
||
* uni-app 按 pages.json 的 subPackage root + path 扫描磁盘上的 .vue 文件。
|
||
*
|
||
* 备份目录放在系统 temp(不在项目内),避免 Vite 扫描 .build 时 EPERM。
|
||
*/
|
||
const fs = require('fs')
|
||
const path = require('path')
|
||
const os = require('os')
|
||
const crypto = require('crypto')
|
||
const { ROOT, parsePagesJson, BRIDGE_ADDON_ROOT } = require('./addon-utils.cjs')
|
||
|
||
const LEGACY_BACKUP_ROOT = path.join(ROOT, '.build', 'addon-pages-backup')
|
||
const SWAP_STATE_FILE = path.join(ROOT, '.build', 'addon-pages-swap.json')
|
||
const BRIDGE_ROOT = BRIDGE_ADDON_ROOT
|
||
|
||
function getBackupRoot() {
|
||
const hash = crypto.createHash('md5').update(ROOT).digest('hex').slice(0, 12)
|
||
return path.join(os.tmpdir(), 'uni-app-addon-pages-backup', hash)
|
||
}
|
||
|
||
function rmDir(dir) {
|
||
if (!fs.existsSync(dir)) return
|
||
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
|
||
}
|
||
|
||
function copyDir(src, dest) {
|
||
fs.mkdirSync(dest, { recursive: true })
|
||
for (const name of fs.readdirSync(src)) {
|
||
const s = path.join(src, name)
|
||
const d = path.join(dest, name)
|
||
if (fs.statSync(s).isDirectory()) copyDir(s, d)
|
||
else fs.copyFileSync(s, d)
|
||
}
|
||
}
|
||
|
||
function moveDir(src, dest) {
|
||
rmDir(dest)
|
||
fs.mkdirSync(path.dirname(dest), { recursive: true })
|
||
try {
|
||
fs.renameSync(src, dest)
|
||
} catch (e) {
|
||
if (e.code !== 'EPERM' && e.code !== 'EXDEV') throw e
|
||
copyDir(src, dest)
|
||
rmDir(src)
|
||
}
|
||
}
|
||
|
||
function readSwapState() {
|
||
if (!fs.existsSync(SWAP_STATE_FILE)) return null
|
||
try {
|
||
return JSON.parse(fs.readFileSync(SWAP_STATE_FILE, 'utf-8'))
|
||
} catch {
|
||
return null
|
||
}
|
||
}
|
||
|
||
function writeSwapState(state) {
|
||
fs.mkdirSync(path.dirname(SWAP_STATE_FILE), { recursive: true })
|
||
fs.writeFileSync(SWAP_STATE_FILE, JSON.stringify(state, null, 2) + '\n', 'utf-8')
|
||
}
|
||
|
||
function clearSwapState() {
|
||
if (fs.existsSync(SWAP_STATE_FILE)) fs.unlinkSync(SWAP_STATE_FILE)
|
||
}
|
||
|
||
function listAddonSubPackageRoots() {
|
||
const pagesJson = parsePagesJson()
|
||
const roots = new Set()
|
||
for (const sub of pagesJson.subPackages || []) {
|
||
if (sub.root?.startsWith('addon/')) roots.add(sub.root)
|
||
}
|
||
return [...roots].sort()
|
||
}
|
||
|
||
function toBackupPagesDir(backupRoot, root) {
|
||
return path.join(backupRoot, root.replace(/^addon\//, ''), 'pages')
|
||
}
|
||
|
||
function toBridgePagesDir(root) {
|
||
return path.join(BRIDGE_ROOT, root.replace(/^addon\//, ''), 'pages')
|
||
}
|
||
|
||
function toSrcPagesDir(root) {
|
||
return path.join(ROOT, 'src', root, 'pages')
|
||
}
|
||
|
||
function applySwap() {
|
||
const backupRoot = getBackupRoot()
|
||
rmDir(backupRoot)
|
||
|
||
let count = 0
|
||
for (const root of listAddonSubPackageRoots()) {
|
||
const pagesDir = toSrcPagesDir(root)
|
||
const bridgePages = toBridgePagesDir(root)
|
||
if (!fs.existsSync(pagesDir) || !fs.existsSync(bridgePages)) continue
|
||
|
||
const backupDir = toBackupPagesDir(backupRoot, root)
|
||
moveDir(pagesDir, backupDir)
|
||
copyDir(bridgePages, pagesDir)
|
||
count++
|
||
}
|
||
|
||
writeSwapState({ backupRoot, appliedAt: new Date().toISOString(), roots: listAddonSubPackageRoots() })
|
||
console.log(`[swap-addon-pages] applied ${count} addon subPackage page dirs -> bridge (${backupRoot})`)
|
||
}
|
||
|
||
function restoreSwap() {
|
||
const state = readSwapState()
|
||
const backupRoot = state?.backupRoot || getBackupRoot()
|
||
if (!fs.existsSync(backupRoot)) {
|
||
clearSwapState()
|
||
return 0
|
||
}
|
||
|
||
let count = 0
|
||
const roots = state?.roots?.length ? state.roots : listAddonSubPackageRoots()
|
||
for (const root of roots) {
|
||
const backupDir = toBackupPagesDir(backupRoot, root)
|
||
const pagesDir = toSrcPagesDir(root)
|
||
if (!fs.existsSync(backupDir)) continue
|
||
rmDir(pagesDir)
|
||
fs.mkdirSync(path.dirname(pagesDir), { recursive: true })
|
||
moveDir(backupDir, pagesDir)
|
||
count++
|
||
}
|
||
|
||
rmDir(backupRoot)
|
||
clearSwapState()
|
||
if (count) {
|
||
console.log(`[swap-addon-pages] restored ${count} addon subPackage page dirs`)
|
||
}
|
||
return count
|
||
}
|
||
|
||
const cmd = process.argv[2] || 'apply'
|
||
if (require.main === module) {
|
||
if (cmd === 'apply') applySwap()
|
||
else if (cmd === 'restore') restoreSwap()
|
||
else if (cmd === 'status') {
|
||
const state = readSwapState()
|
||
console.log('[swap-addon-pages] state:', state || 'idle')
|
||
console.log('[swap-addon-pages] legacy backup exists:', fs.existsSync(LEGACY_BACKUP_ROOT))
|
||
} else {
|
||
console.error('Usage: node swap-addon-pages.cjs apply|restore|status')
|
||
process.exit(1)
|
||
}
|
||
}
|
||
|
||
module.exports = {
|
||
applySwap,
|
||
restoreSwap,
|
||
listAddonSubPackageRoots,
|
||
getBackupRoot,
|
||
LEGACY_BACKUP_ROOT
|
||
}
|