import { dirname, join } from "../../deno_ral/path.ts";
import { ensureDirSync } from "../../deno_ral/fs.ts";
import { PublishFiles } from "../provider-types.ts";
import { TempContext } from "../../core/temp-types.ts";
import { md5HashBytes } from "../../core/hash.ts";
import { createTarFromFiles } from "../../deno_ral/tar.ts";
interface ManifestMetadata {
appmode: string;
primary_rmd: string | null;
primary_html: string;
content_category: string | null;
has_parameters: boolean;
}
interface Manifest {
version: number;
locale: string;
platform: string;
metadata: ManifestMetadata;
packages: null;
files: Record<string, { checksum: string }>;
users: null;
}
export interface BundleData {
bundlePath: string;
manifest: Manifest;
}
export async function createBundle(
type: "site" | "document",
files: PublishFiles,
tempContext: TempContext,
): Promise<BundleData> {
const manifestFiles: Record<string, { checksum: string }> = {};
for (const file of files.files) {
const filePath = join(files.baseDir, file);
if (Deno.statSync(filePath).isFile) {
const fileBytes = Deno.readFileSync(filePath);
const checksum = await md5HashBytes(fileBytes);
manifestFiles[file] = { checksum };
}
}
const manifest = {
version: 1,
locale: "en_US",
platform: "4.2.0",
metadata: {
appmode: "static",
primary_rmd: null,
primary_html: files.rootFile,
content_category: type === "site" ? "site" : null,
has_parameters: false,
},
packages: null,
files: manifestFiles,
users: null,
};
const stageDir = tempContext.createDir();
files.files.forEach((file) => {
const filePath = join(files.baseDir, file);
if (Deno.statSync(filePath).isFile) {
const targetDir = join(stageDir, dirname(file));
ensureDirSync(targetDir);
Deno.copyFileSync(filePath, join(stageDir, file));
}
});
Deno.writeTextFileSync(
join(stageDir, "manifest.json"),
JSON.stringify(manifest, undefined, 2),
);
const tarFiles = [...files.files, "manifest.json"];
const tarFile = tempContext.createFile({ suffix: ".tar" });
await createTarFromFiles(tarFile, tarFiles, { baseDir: stageDir });
const targzFile = `${tarFile}.gz`;
const src = await Deno.open(tarFile);
const dest = await Deno.open(targzFile, {
create: true,
write: true,
});
await src.readable
.pipeThrough(new CompressionStream("gzip"))
.pipeTo(dest.writable);
return {
bundlePath: targzFile,
manifest,
};
}