const archiver = require('archiver'); const fs = require('fs'); const process = require('process'); const path = require('path'); const sys = require('child_process'); function rm(dst) { if(!fs.existsSync(dst)) { return; } let stat = fs.statSync(dst); if(stat.isDirectory()) { let stack = []; let files = []; let dirs = [dst]; let root = fs.readdirSync(dst); for (let r of root) { let p = path.join(dst, r); let stat = fs.statSync(p); if (stat.isDirectory()) { stack.push(p); dirs.push(p); } else { files.push(p); } } while (stack.length > 0) { let p = stack.pop(); let root = fs.readdirSync(p); for (let r of root) { let sp = path.join(p, r); let stat = fs.statSync(sp); if (stat.isDirectory()) { stack.push(sp); dirs.push(sp); } else if (stat.isFile()) { files.push(sp); } } } for(let f of files) { fs.unlinkSync(f); } dirs.sort((l, r) => { let ll = l.length; let rl = r.length; if (ll < rl) { return 1; } else if (ll == rl) { return 0; } else { return -1; } }); let end = 0; for (let i = 0; i < dirs.length; ++i) { if (dirs[end] != dirs[i]) { dirs[++end] = dirs[i]; } } end += 1; for (let i = 0; i < end; ++i) { if (fs.readdirSync(dirs[i]).length == 0) { fs.rmdirSync(dirs[i]); } } } } function mv(src, dst) { if (!fs.existsSync(src)) { throw `${src} is not exists`; } let lstat = fs.statSync(src); if (lstat.isFile()) { if (!fs.existsSync(dst)) { fs.renameSync(src, dst); return; } if(fs.existsSync(dst)) { let rstat = fs.statSync(dst); if(rstat.isFile()) { fs.unlinkSync(dst); } else if(rstat.isDirectory()) { dst = path.join(dst, path.basename(src)); } else { throw `unsupport dst type ${dst}`; } } if(fs.existsSync(dst)) { fs.unlinkSync(dst); } fs.renameSync(src, dst); return; } if (lstat.isDirectory()) { if(!fs.existsSync(dst)) { fs.mkdirSync(dst, { recursive: true }); } let rstat = fs.statSync(dst); if(rstat.isFile()) { throw `can't move from directory to a file`; } if(!rstat.isDirectory()) { throw `unsupport dst type ${dst}`; } let stack = []; let files = []; let root = fs.readdirSync(src); for(let r of root) { let p = path.join(src, r); let stat = fs.statSync(p); if(stat.isDirectory()) { stack.push(p); files.push([p, true]); } else { files.push([p, false]); } } while(stack.length > 0) { let p = stack.pop(); let root = fs.readdirSync(p); for(let r of root) { let sp = path.join(p, r); let stat = fs.statSync(sp); if(stat.isDirectory()) { stack.push(sp); files.push([sp, true]); } else if(stat.isFile()) { files.push([sp, false]); } } } let dirs = []; src = path.join(path.dirname(src), path.basename(src)); dirs.push(src); for(let f of files) { let d = path.join(dst, f[0].substr(src.length)); let b = ""; if(f[1]) { fs.mkdirSync(d, { recursive: true }); dirs.push(f[0]); b = f[0]; } else { try { fs.mkdirSync(path.dirname(d), { recursive: true }); } catch(e) { // ignore error } fs.renameSync(f[0], d); b = path.dirname(f[0]); } } dirs.sort((l, r) => { let ll = l.length; let rl = r.length; if(ll < rl) { return 1; } else if(ll == rl) { return 0; } else { return -1; } }); let end = 0; for(let i = 0; i < dirs.length; ++i) { if(dirs[end] != dirs[i]) { dirs[++end] = dirs[i]; } } end += 1; for(let i = 0; i < end; ++i) { if(fs.readdirSync(dirs[i]).length == 0) { fs.rmdirSync(dirs[i]); } } return; } throw `unsupport src type ${src}`; } function cp(src, dst) { let copy = (src, dst) => { let from = fs.createReadStream(src); let to = fs.createWriteStream(dst); from.pipe(to); }; if (!fs.existsSync(src)) { throw `${src} is not exists`; } let lstat = fs.statSync(src); if (lstat.isFile()) { if(!fs.existsSync(dst)) { copy(src, dst); return; } if (fs.existsSync(dst)) { let rstat = fs.statSync(dst); if(rstat.isFile()) { fs.unlinkSync(dst); } else if(rstat.isDirectory()) { dst = path.join(dst, path.basename(src)); } else { throw `unsupport dst type ${dst}` } } if(fs.existsSync(dst)) { fs.unlinkSync(dst); } copy(src, dst); return; } if (lstat.isDirectory()) { if (!fs.existsSync(dst)) { fs.mkdirSync(dst, { recursive: true }); } let rstat = fs.statSync(dst); if (rstat.isFile()) { throw `can't copy from directory to a file`; } if (!rstat.isDirectory()) { throw `unsupport dst type ${dst}`; } let stack = []; let files = []; let root = fs.readdirSync(src); for (let r of root) { let p = path.join(src, r); let stat = fs.statSync(p); if (stat.isDirectory()) { stack.push(p); } else if (stat.isFile()) { files.push(p); } } while (stack.length > 0) { let p = stack.pop(); let root = fs.readdirSync(p); for (let r of root) { let sp = path.join(p, r) let stat = fs.statSync(sp); if (stat.isDirectory()) { stack.push(sp); } else if (stat.isFile()) { files.push(sp); } } } src = path.join(path.dirname(src), path.basename(src)); for (let f of files) { let d = path.join(dst, f.substr(src.length)); try { fs.mkdirSync(path.dirname(d), { recursive: true }); } catch (e) { // ignore error } copy(f, d); } return; } throw `unsuppot src type ${src}`; } function build_frontend(dst) { const oldpath = process.cwd(); let d = path.join(oldpath, dst); process.chdir('frontend'); sys.execSync('npm install'); sys.execSync('npm run build'); cp('dist', path.join(d, 'dist')); process.chdir(oldpath); } function build_backend(dst) { const oldpath = process.cwd(); let d = path.join(oldpath, dst); process.chdir('backend'); sys.execSync('go build'); if(process.platform === 'win32') { mv('backend.exe', d); } else { mv('backend', d); } cp('backend.toml', d); process.chdir(oldpath); } function build() { let d = new Date(); let base = `mo-${process.platform}-${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()}-${d.getHours()}${d.getMinutes()}${d.getSeconds()}`; let dir = 'mo'; let dst = path.join(dir, base); if(fs.existsSync(dir)) { rm(dir); } fs.mkdirSync(dst, { recursive: true }); build_frontend(dst); build_backend(dst); let out = `${base}.zip`; if(fs.existsSync(out)) { fs.unlinkSync(out); } let zip = fs.createWriteStream(out); let archive = archiver('zip', { zlib: {level: 9} }); zip.on('close', () => { rm(dir); }); archive.pipe(zip); archive.on('error', err => { throw err; }); archive.directory(dst, base); archive.finalize(); } build();