import AdmZip from "adm-zip"; import path from "path"; import fs from "fs"; import { execSync } from "child_process"; import { createLog } from "../services/logger/logger.js"; import { getAppInfo } from "../globalUtils/appInfo.js"; // create the ignore list const ignoreList = [ ".git", "builds", "server", "node_modules", "apiDocsLSTV2", "testFiles", ".env", ".gitignore", ".versionrc.json", "drizzle-dev.config.ts", "nssm.exe", "postgresql-17.2-3-windows-x64.exe", // front end ignore "frontend/node_modules", "fonrtend/.env", "frontend/public", "frontend/src", "frontend/.gitignore", "frontend/eslint.config.js", "frontend/index.html", "frontend/package.json", "frontend/package-lock.json", "frontend/README.md", "frontend/tsconfig.json", "frontend/tsconfig.app.json", "frontend/tsconfig.node.json", "frontend/vite.config.ts", "frontend/components.json", //misc files "jsTesting", ]; const shouldIgnore = (itemPath: any) => { const normalizedItemPath = itemPath.replace(/\\/g, "/"); return ignoreList.some((ignorePattern) => { const normalizedIgnorePatther = ignorePattern.replace(/\\/g, "/"); return ( normalizedItemPath === normalizedIgnorePatther || normalizedItemPath.startsWith(`${normalizedIgnorePatther}/`) ); }); }; const addToZip = (zip: any, currentPath: string, rootPath: string) => { const items = fs.readdirSync(currentPath); items.forEach((item) => { const itemPath = path.join(currentPath, item); const relativePath = path.relative(rootPath, itemPath); // Skip if the item is in the ignore list if (shouldIgnore(relativePath)) { createLog("info", "lst", "zipUpBuild", `Ignoring: ${relativePath}`); return; } const stat = fs.statSync(itemPath); if (stat.isDirectory()) { // If it's a directory, recursively add its contents addToZip(zip, itemPath, rootPath); } else { // If it's a file, add it to the zip with the preserved folder structure zip.addLocalFile(itemPath, path.dirname(relativePath)); } }); }; const updateBuildNumber = (appLock: string) => { const packagePath = path.join(appLock, "package.json"); // Adjust path if necessary try { // Read package.json const pkgData = fs.readFileSync(packagePath, "utf8"); const pkgJson = JSON.parse(pkgData); // Ensure admConfig exists if (pkgJson.admConfig && typeof pkgJson.admConfig.build === "number") { // Increment the build number pkgJson.admConfig.build += 1; // Write the updated data back fs.writeFileSync( packagePath, JSON.stringify(pkgJson, null, 2), "utf8" ); createLog( "info", "lst", "zipUpBuild", `Build number updated to: ${pkgJson.admConfig.build}` ); // Auto-commit changes execSync("git add package.json"); execSync( `git commit -m "ci(release): bump build number to ${pkgJson.admConfig.build}"` ); } else { createLog( "error", "lst", "zipUpBuild", "admConfig.build is missing or not a number" ); } } catch (error) { createLog( "error", "lst", "zipUpBuild", `Error updating build number: ${error}` ); } }; export const createZip = async (appLock: string) => { const app = await getAppInfo(appLock); const zip = new AdmZip(); //dest path for this app... hard coded for meow will be in db later const destPath = `${process.env.DEVFOLDER}\\builds`; const srcPath = `${process.env.DEVFOLDER}`; addToZip(zip, srcPath, srcPath); // Write the zip file to disk const outputZipPath = path.join( destPath, `${app.name}-${app.version}-${app.admConfig.build}.zip` ); zip.writeZip(outputZipPath); createLog( "info", "lst", "zipUpBuild", `Zip file created at ${outputZipPath}` ); updateBuildNumber(appLock); // only keep the last 5 builds for the type we have. try { const appFiles = fs .readdirSync(destPath) .filter((file) => file.startsWith(app.name)) // Ensure only backend files are matched .map((file) => ({ name: file, time: fs.statSync(path.join(destPath, file)).mtime.getTime(), })) .sort((a, b) => a.time - b.time); // Sort by modification time (oldest first) createLog( "info", "lst", "zipUpBuild", `app Files (sorted by time):", ${JSON.stringify(appFiles)}` ); if (appFiles.length > 20) { appFiles.slice(0, -20).forEach((file) => { const filePath = path.join(destPath, file.name); try { fs.unlinkSync(filePath); createLog( "info", "lst", "zipUpBuild", `Deleted: ${file.name}` ); } catch (error: any) { createLog( "error", "lst", "zipUpBuild", `Failed to delete ${file.name}: ${error.message}` ); } }); } else { createLog("info", "lst", "zipUpBuild", "No files to delete."); } } catch (error: any) { createLog( "error", "lst", "zipUpBuild", `Error reading directory or deleting files:", ${error.message}` ); } }; //createZip("C:\\Users\\matthes01\\Documents\\lstv2"); // Only call `createZip` if the script is executed directly if (process.argv.length > 2) { const location = process.argv[2]; if (!location) { createLog("error", "lst", "zipUpBuild", "Error: No location provided."); process.exit(1); } else { createLog("info", "lst", "zipUpBuild", "Startiing the zip process."); } createZip(location); } else { createLog("error", "lst", "zipUpBuild", "Error: No location provided."); }