@licq/tpkg
Version:
pack or unpack wechatapp and qqminiapp package
166 lines (144 loc) • 4.38 kB
JavaScript
const path = require("path");
const fs = require("fs");
/**
* pack dir to pkg
* @name pack
* @param {pathLike} sourceDir [required] The directory to work with
* @param {pathLike} targetPath [optional] The target path, The default path is the same as the sourceDir.
* @param {string} targetName [optional] The target filename, The default name is the same as the sourceDir.
* @since v1.0.0
* @returns pathLike
* @example
* const tpkg = require('@licq/tpkg')
* const res = tpkg.pack('path/to/dir/');
* const res = tpkg.pack('path/to/dir/', 'path/to/dir/demo');
* const res = tpkg.pack('path/to/dir/', 'path/to/dir/demo', 'demo.wxvpkg') // or demo.tqapkg
* //==> eg: path/to/dir/demo.wxvpkg
*/
function pack(sourceDir, targetPath, targetName) {
if (!fs.existsSync(sourceDir)) {
return console.log(`\nsourceDir ${sourceDir} does not exist.\n`);
}
if(targetPath){
if(!fs.existsSync(targetPath)){
return console.log(`\ntargetPath ${targetPath} does not exist.\n`);
}
}else{
targetPath = path.dirname(sourceDir);
}
if(!targetName){
targetName = `${path.basename(sourceDir)}.wxvpkg`
}
targetPath = path.join(targetPath, targetName);
const fd = fs.openSync(targetPath, "w");
function writeSync(buf, start) {
fs.writeSync(fd, buf, 0, buf.length, start);
}
function writeInt32(number, start) {
let buf = Buffer.alloc(4);
buf.writeInt32BE(number, 0);
writeSync(buf, start);
}
let files = fs.readdirSync(sourceDir);
let totalCount = files.length;
let buf = Buffer.alloc(4);
buf.writeInt32BE(totalCount, 0);
writeSync(buf, 14);
let start = 18;
// 12 + /name.length
let dataOffset = start;
for (let file of files) {
let name = `/${file}`;
let buf = Buffer.from(name, "utf8");
dataOffset = dataOffset + 12 + buf.length;
}
for (let file of files) {
let nb = Buffer.from(`/${file}`, "utf8");
// write filename byte length
writeInt32(nb.length, start);
start += 4;
// write filename
writeSync(nb, start);
start += nb.length;
// write offset
writeInt32(dataOffset, start);
start += 4;
// write length
let contentBuf = fs.readFileSync(path.join(sourceDir, file));
writeInt32(contentBuf.length, start);
start += 4;
// write content
writeSync(contentBuf, dataOffset);
dataOffset += contentBuf.length;
}
fs.closeSync(fd);
return targetPath;
}
/**
* unpack pkg
* @name unpack
* @param {pathLike} pkgPath [required] The pkgPath to work with
* @param {pathLike} targetPath [optional] The target path, The default is the same as the pkgPath.
* @since v1.0.0
* @returns pathLike
* @example
* const tpkg = require('@licq/tpkg')
* const res = tpkg.unpack('path/to/dir/demo.wxvpkg', _dirname) // or demo.tqapkg
* //==> eg: ${_dirname}/demo/**
*/
function unpack(pkgPath, targetPath) {
if (!fs.existsSync(pkgPath)) {
return console.log(`\npkgPath ${pkgPath} does not exist.\n`);
}
if (targetPath) {
if (!fs.existsSync(targetPath)) {
return console.log(`\ntargetPath ${targetPath} does not exist.\n`);
}
} else {
targetPath = path.dirname(pkgPath);
}
targetPath = path.join(
targetPath,
path.basename(pkgPath, path.extname(pkgPath))
);
const fd = fs.openSync(pkgPath, "r");
// read buffer
function readSync(start, length) {
const n = Buffer.alloc(length);
fs.readSync(fd, n, 0, length, start);
return n;
}
const totalCount = readSync(14, 4).readInt32BE(0);
const map = {};
let n = 18;
for (let i = 0; i < totalCount; i++) {
const e = {};
// byte length of filename
const i = readSync(n, 4).readInt32BE(0);
n += 4;
e.name = readSync(n, i).toString();
n += i;
e.offset = readSync(n, 4).readInt32BE(0);
n += 4;
e.length = readSync(n, 4).readInt32BE(0);
n += 4;
map[e.name] = e;
}
let created = [];
for (let item of Object.values(map)) {
let dir = path.join(targetPath, path.dirname(item.name));
if (created.indexOf(dir) == -1) {
fs.mkdirSync(dir, { recursive: true });
created.push(dir);
}
let buf = readSync(item.offset, item.length);
let filepath = path.join(targetPath, item.name);
fs.writeFileSync(filepath, buf.toString("utf8"), "utf8");
}
fs.closeSync(fd);
return targetPath;
}
module.exports = {
pack,
unpack,
};