Adding unpack as cli command and exposing via index.ts for typescript usage. (#5)

This commit is contained in:
Suyog Sonwalkar 2025-06-28 19:41:53 -04:00 • committed by GitHub
commit 2c1d058085
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 180 additions and 1 deletions

View file

@ -10,6 +10,7 @@ import { signDxtFile, unsignDxtFile, verifyDxtFile } from "../node/sign.js";
import { validateManifest } from "../node/validate.js";
import { initExtension } from "./init.js";
import { packExtension } from "./pack.js";
import { unpackExtension } from "./unpack.js";
// ES modules equivalent of __dirname
const __filename = fileURLToPath(import.meta.url);
@ -94,6 +95,27 @@ program
})();
});
// Unpack command
program
.command("unpack <dxt-file> [output]")
.description("Unpack a DXT extension file")
.action((dxtFile: string, output?: string) => {
void (async () => {
try {
const success = await unpackExtension({
dxtPath: dxtFile,
outputDir: output,
});
process.exit(success ? 0 : 1);
} catch (error) {
console.error(
`ERROR: ${error instanceof Error ? error.message : "Unknown error"}`,
);
process.exit(1);
}
})();
});
// Sign command
program
.command("sign <dxt-file>")

61
src/cli/unpack.ts Normal file
View file

@ -0,0 +1,61 @@
import { unzipSync } from "fflate";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import { join, resolve } from "path";
import { extractSignatureBlock } from "../node/sign.js";
import { getLogger } from "../shared/log.js";
interface UnpackOptions {
dxtPath: string;
outputDir?: string;
silent?: boolean;
}
export async function unpackExtension({
dxtPath,
outputDir,
silent,
}: UnpackOptions): Promise<boolean> {
const logger = getLogger({ silent });
const resolvedDxtPath = resolve(dxtPath);
if (!existsSync(resolvedDxtPath)) {
logger.error(`ERROR: DXT file not found: ${dxtPath}`);
return false;
}
const finalOutputDir = outputDir ? resolve(outputDir) : process.cwd();
if (!existsSync(finalOutputDir)) {
mkdirSync(finalOutputDir, { recursive: true });
}
try {
const fileContent = readFileSync(resolvedDxtPath);
const { originalContent } = extractSignatureBlock(fileContent);
const decompressed = unzipSync(originalContent);
for (const relativePath in decompressed) {
if (Object.prototype.hasOwnProperty.call(decompressed, relativePath)) {
const data = decompressed[relativePath];
const fullPath = join(finalOutputDir, relativePath);
const dir = join(fullPath, "..");
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
writeFileSync(fullPath, data);
}
}
logger.log(`Extension unpacked successfully to ${finalOutputDir}`);
return true;
} catch (error) {
if (error instanceof Error) {
logger.error(`ERROR: Failed to unpack extension: ${error.message}`);
} else {
logger.error("ERROR: An unknown error occurred during unpacking.");
}
return false;
}
}