import { mkdirSync, mkdtempSync, readdirSync, createReadStream, createWriteStream, existsSync, } from "fs"; import { copyFile, readFile, writeFile, rm } from "fs/promises"; import { tmpdir } from "os"; import { join } from "path"; import * as tar from "tar-stream"; import { createGzip } from "zlib"; import { parse as yamlParse } from "yaml"; const projectDir = process.env["INPUT_PROJECTDIR"]; const filesDir = process.env["INPUT_FILESDIR"]; const output = process.env["INPUT_OUTPUT"]; if (!projectDir || !filesDir || !output) { console.error("Missing required input(s)."); process.exit(1); } const tempdir = (name) => { const dir = mkdtempSync(join(tmpdir(), name)); return dir; }; const mkdir = (dir, recursive = false) => { mkdirSync(dir, { recursive }); return dir; }; const getMetaFiles = (root) => { const recurse = (dir) => { const entries = readdirSync(join(root, dir), { withFileTypes: true }); let files = []; for (const entry of entries) { const fullPath = join(dir, entry.name); if (entry.isDirectory()) { files = files.concat(recurse(fullPath)); } else if (entry.name.endsWith(".meta")) { files.push(fullPath); } } return files; }; return recurse("."); }; const createUnityPackage = async () => { const metaFiles = getMetaFiles(join(projectDir, filesDir)); const tempDir = tempdir("unitypackage-create-"); for await (const metaFile of metaFiles) { const assetPath = metaFile.replace(/\.meta$/, ""); const metaPath = join(projectDir, filesDir, metaFile); const meta = yamlParse(await readFile(metaPath, "utf8")); const guid = meta.guid; if (!guid) continue; const dir = mkdir(join(tempDir, guid), true); const assetFullPath = join(projectDir, filesDir, assetPath); if (!meta.folderAsset && existsSync(assetFullPath)) { await copyFile(assetFullPath, join(dir, "asset")); } await copyFile(metaPath, join(dir, "asset.meta")); await writeFile(join(dir, "pathname"), join(filesDir, assetPath)); } const pack = tar.pack(); for (const guidDir of readdirSync(tempDir)) { const entryDir = join(tempDir, guidDir); for (const entry of readdirSync(entryDir)) { const filePath = join(entryDir, entry); const stream = createReadStream(filePath); const buffer = await new Promise((resolve) => { const chunks = []; stream.on("data", (chunk) => chunks.push(chunk)); stream.on("end", () => resolve(Buffer.concat(chunks))); }); pack.entry({ name: join(guidDir, entry), type: "file" }, buffer); } } pack.finalize(); const writeStream = createWriteStream(output); pack.pipe(createGzip()).pipe(writeStream); await new Promise((resolve, reject) => { writeStream.on("finish", resolve); writeStream.on("error", reject); }); await rm(tempDir, { recursive: true, force: true }); console.log(`UnityPackage created: ${output}`); }; createUnityPackage();