89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
|
|
import fs from 'node:fs/promises';
|
|||
|
|
import path from 'node:path';
|
|||
|
|
|
|||
|
|
const projectRoot = process.cwd();
|
|||
|
|
|
|||
|
|
const distDir = path.join(projectRoot, 'dist');
|
|||
|
|
const deployDir = path.join(projectRoot, 'deploy_bundle');
|
|||
|
|
const deployWebDir = path.join(deployDir, 'web');
|
|||
|
|
const deployServerDir = path.join(deployDir, 'server');
|
|||
|
|
|
|||
|
|
const exists = async (p) => {
|
|||
|
|
try {
|
|||
|
|
await fs.access(p);
|
|||
|
|
return true;
|
|||
|
|
} catch {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const ensureDir = async (p) => {
|
|||
|
|
await fs.mkdir(p, { recursive: true });
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const emptyDir = async (p) => {
|
|||
|
|
await fs.rm(p, { recursive: true, force: true });
|
|||
|
|
await fs.mkdir(p, { recursive: true });
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const copyDir = async (src, dest) => {
|
|||
|
|
await fs.cp(src, dest, { recursive: true });
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const copyFile = async (src, dest) => {
|
|||
|
|
await ensureDir(path.dirname(dest));
|
|||
|
|
await fs.copyFile(src, dest);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (!(await exists(distDir))) {
|
|||
|
|
throw new Error('未找到 dist/。请先执行:npm run build');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1) web: dist/ 下除 api/ 之外所有内容
|
|||
|
|
await emptyDir(deployWebDir);
|
|||
|
|
|
|||
|
|
const distEntries = await fs.readdir(distDir, { withFileTypes: true });
|
|||
|
|
for (const entry of distEntries) {
|
|||
|
|
if (entry.name === 'api') continue;
|
|||
|
|
const src = path.join(distDir, entry.name);
|
|||
|
|
const dest = path.join(deployWebDir, entry.name);
|
|||
|
|
if (entry.isDirectory()) {
|
|||
|
|
await copyDir(src, dest);
|
|||
|
|
} else {
|
|||
|
|
await copyFile(src, dest);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2) server: dist/api -> deploy_bundle/server/dist/api
|
|||
|
|
await ensureDir(deployServerDir);
|
|||
|
|
await ensureDir(path.join(deployServerDir, 'dist'));
|
|||
|
|
|
|||
|
|
const distApiDir = path.join(distDir, 'api');
|
|||
|
|
if (!(await exists(distApiDir))) {
|
|||
|
|
throw new Error('未找到 dist/api/。请确认 npm run build 已成功执行(包含 scripts/build-api.mjs)。');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await emptyDir(path.join(deployServerDir, 'dist', 'api'));
|
|||
|
|
await copyDir(distApiDir, path.join(deployServerDir, 'dist', 'api'));
|
|||
|
|
|
|||
|
|
// 3) 同步 server 运行所需文件
|
|||
|
|
await copyFile(path.join(projectRoot, 'package.json'), path.join(deployServerDir, 'package.json'));
|
|||
|
|
if (await exists(path.join(projectRoot, 'package-lock.json'))) {
|
|||
|
|
await copyFile(path.join(projectRoot, 'package-lock.json'), path.join(deployServerDir, 'package-lock.json'));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ecosystem.config.cjs:以仓库根目录为准同步(如需环境差异,可在服务器上覆盖 env/cwd)
|
|||
|
|
if (await exists(path.join(projectRoot, 'ecosystem.config.cjs'))) {
|
|||
|
|
await copyFile(path.join(projectRoot, 'ecosystem.config.cjs'), path.join(deployServerDir, 'ecosystem.config.cjs'));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// sanity check
|
|||
|
|
const initSql = path.join(deployServerDir, 'dist', 'api', 'database', 'init.sql');
|
|||
|
|
if (!(await exists(initSql))) {
|
|||
|
|
throw new Error('缺少 deploy_bundle/server/dist/api/database/init.sql(postbuild 应该会复制)。');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('deploy_bundle 已生成:');
|
|||
|
|
console.log('- deploy_bundle/web');
|
|||
|
|
console.log('- deploy_bundle/server');
|