rename dxt -> mcpb

This commit is contained in:
Joan Xie 2025-08-21 14:56:54 -07:00
commit e1938b9933
No known key found for this signature in database
3 changed files with 575 additions and 427 deletions

View file

@ -8,7 +8,7 @@ export const EXCLUDE_PATTERNS = [
"Thumbs.db",
".gitignore",
".git",
".dxtignore",
".mcpbignore",
"*.log",
".env*",
".npm",
@ -33,30 +33,30 @@ export const EXCLUDE_PATTERNS = [
"yarn-error.log*",
"package-lock.json",
"yarn.lock",
"*.dxt",
"*.mcpb",
"*.d.ts",
"*.tsbuildinfo",
"tsconfig.json",
];
/**
* Read and parse .dxtignore file patterns
* Read and parse .mcpbignore file patterns
*/
export function readDxtIgnorePatterns(baseDir: string): string[] {
const dxtIgnorePath = join(baseDir, ".dxtignore");
if (!existsSync(dxtIgnorePath)) {
export function readMcpbIgnorePatterns(baseDir: string): string[] {
const mcpbIgnorePath = join(baseDir, ".mcpbignore");
if (!existsSync(mcpbIgnorePath)) {
return [];
}
try {
const content = readFileSync(dxtIgnorePath, "utf-8");
const content = readFileSync(mcpbIgnorePath, "utf-8");
return content
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.length > 0 && !line.startsWith("#"));
} catch (error) {
console.warn(
`Warning: Could not read .dxtignore file: ${error instanceof Error ? error.message : "Unknown error"}`,
`Warning: Could not read .mcpbignore file: ${error instanceof Error ? error.message : "Unknown error"}`,
);
return [];
}

View file

@ -6,30 +6,30 @@ import { tmpdir } from "os";
import { join } from "path";
import { promisify } from "util";
import type { DxtSignatureInfo } from "../types.js";
import type { McpbSignatureInfo } from "../types.js";
// Signature block markers
const SIGNATURE_HEADER = "DXT_SIG_V1";
const SIGNATURE_FOOTER = "DXT_SIG_END";
const SIGNATURE_HEADER = "MCPB_SIG_V1";
const SIGNATURE_FOOTER = "MCPB_SIG_END";
const execFileAsync = promisify(execFile);
/**
* Signs a DXT file with the given certificate and private key using PKCS#7
* Signs a MCPB file with the given certificate and private key using PKCS#7
*
* @param dxtPath Path to the DXT file to sign
* @param mcpbPath Path to the MCPB file to sign
* @param certPath Path to the certificate file (PEM format)
* @param keyPath Path to the private key file (PEM format)
* @param intermediates Optional array of intermediate certificate paths
*/
export function signDxtFile(
dxtPath: string,
export function signMcpbFile(
mcpbPath: string,
certPath: string,
keyPath: string,
intermediates?: string[],
): void {
// Read the original DXT file
const dxtContent = readFileSync(dxtPath);
// Read the original MCPB file
const mcpbContent = readFileSync(mcpbPath);
// Read certificate and key
const certificatePem = readFileSync(certPath, "utf-8");
@ -42,7 +42,7 @@ export function signDxtFile(
// Create PKCS#7 signed data
const p7 = forge.pkcs7.createSignedData();
p7.content = forge.util.createBuffer(dxtContent);
p7.content = forge.util.createBuffer(mcpbContent);
// Parse and add certificates
const signingCert = forge.pki.certificateFromPem(certificatePem);
@ -88,22 +88,22 @@ export function signDxtFile(
// Create signature block with PKCS#7 data
const signatureBlock = createSignatureBlock(pkcs7Signature);
// Append signature block to DXT file
const signedContent = Buffer.concat([dxtContent, signatureBlock]);
writeFileSync(dxtPath, signedContent);
// Append signature block to MCPB file
const signedContent = Buffer.concat([mcpbContent, signatureBlock]);
writeFileSync(mcpbPath, signedContent);
}
/**
* Verifies a signed DXT file using OS certificate store
* Verifies a signed MCPB file using OS certificate store
*
* @param dxtPath Path to the signed DXT file
* @param mcpbPath Path to the signed MCPB file
* @returns Signature information including verification status
*/
export async function verifyDxtFile(
dxtPath: string,
): Promise<DxtSignatureInfo> {
export async function verifyMcpbFile(
mcpbPath: string,
): Promise<McpbSignatureInfo> {
try {
const fileContent = readFileSync(dxtPath);
const fileContent = readFileSync(mcpbPath);
// Find and extract signature block
const { originalContent, pkcs7Signature } =
@ -213,7 +213,7 @@ export async function verifyDxtFile(
.toHex(),
};
} catch (error) {
throw new Error(`Failed to verify DXT file: ${error}`);
throw new Error(`Failed to verify MCPB file: ${error}`);
}
}
@ -239,7 +239,7 @@ function createSignatureBlock(pkcs7Signature: Buffer): Buffer {
}
/**
* Extracts the signature block from a signed DXT file
* Extracts the signature block from a signed MCPB file
*/
export function extractSignatureBlock(fileContent: Buffer): {
originalContent: Buffer;
@ -302,7 +302,7 @@ export async function verifyCertificateChain(
let tempDir: string | null = null;
try {
tempDir = await mkdtemp(join(tmpdir(), "dxt-verify-"));
tempDir = await mkdtemp(join(tmpdir(), "mcpb-verify-"));
const certChainPath = join(tempDir, "chain.pem");
const certChain = [certificate, ...(intermediates || [])].join("\n");
await writeFile(certChainPath, certChain);
@ -400,10 +400,10 @@ export async function verifyCertificateChain(
}
/**
* Removes signature from a DXT file
* Removes signature from a MCPB file
*/
export function unsignDxtFile(dxtPath: string): void {
const fileContent = readFileSync(dxtPath);
export function unsignMcpbFile(mcpbPath: string): void {
const fileContent = readFileSync(mcpbPath);
const { originalContent } = extractSignatureBlock(fileContent);
writeFileSync(dxtPath, originalContent);
writeFileSync(mcpbPath, originalContent);
}

View file

@ -6,8 +6,8 @@ import { join, resolve } from "path";
import prettyBytes from "pretty-bytes";
import { unpackExtension } from "../cli/unpack.js";
import { DxtManifestSchema } from "../schemas.js";
import { DxtManifestSchema as LooseDxtManifestSchema } from "../schemas-loose.js";
import { McpbManifestSchema } from "../schemas.js";
import { McpbManifestSchema as LooseMcpbManifestSchema } from "../schemas-loose.js";
export function validateManifest(inputPath: string): boolean {
try {
@ -22,7 +22,7 @@ export function validateManifest(inputPath: string): boolean {
const manifestContent = readFileSync(manifestPath, "utf-8");
const manifestData = JSON.parse(manifestContent);
const result = DxtManifestSchema.safeParse(manifestData);
const result = McpbManifestSchema.safeParse(manifestData);
if (result.success) {
console.log("Manifest is valid!");
@ -57,26 +57,26 @@ export function validateManifest(inputPath: string): boolean {
}
}
export async function cleanDxt(inputPath: string) {
const tmpDir = await fs.mkdtemp(resolve(os.tmpdir(), "dxt-clean-"));
const dxtPath = resolve(tmpDir, "in.dxt");
export async function cleanMcpb(inputPath: string) {
const tmpDir = await fs.mkdtemp(resolve(os.tmpdir(), "mcpb-clean-"));
const mcpbPath = resolve(tmpDir, "in.mcpb");
const unpackPath = resolve(tmpDir, "out");
console.log(" -- Cleaning DXT...");
console.log(" -- Cleaning MCPB...");
try {
await fs.copyFile(inputPath, dxtPath);
console.log(" -- Unpacking DXT...");
await unpackExtension({ dxtPath, silent: true, outputDir: unpackPath });
await fs.copyFile(inputPath, mcpbPath);
console.log(" -- Unpacking MCPB...");
await unpackExtension({ mcpbPath, silent: true, outputDir: unpackPath });
const manifestPath = resolve(unpackPath, "manifest.json");
const originalManifest = await fs.readFile(manifestPath, "utf-8");
const manifestData = JSON.parse(originalManifest);
const result = LooseDxtManifestSchema.safeParse(manifestData);
const result = LooseMcpbManifestSchema.safeParse(manifestData);
if (!result.success) {
throw new Error(
`Unrecoverable manifest issues, please run "dxt validate"`,
`Unrecoverable manifest issues, please run "mcpb validate"`,
);
}
await fs.writeFile(manifestPath, JSON.stringify(result.data, null, 2));
@ -85,9 +85,9 @@ export async function cleanDxt(inputPath: string) {
originalManifest.trim() !==
(await fs.readFile(manifestPath, "utf8")).trim()
) {
console.log(" -- Update manifest to be valid per DXT schema");
console.log(" -- Update manifest to be valid per MCPB schema");
} else {
console.log(" -- Manifest already valid per DXT schema");
console.log(" -- Manifest already valid per MCPB schema");
}
const nodeModulesPath = resolve(unpackPath, "node_modules");