UNPKG

@capawesome/cli

Version:

The Capawesome Cloud Command Line Interface (CLI) to manage Live Updates and more.

61 lines (60 loc) 2.58 kB
import { UserError } from '../utils/error.js'; import AdmZip from 'adm-zip'; import { globby } from 'globby'; import path from 'path'; const MAX_ZIP_ENTRIES = 65535; class ZipImpl { async zipFolder(sourceFolder) { const zip = new AdmZip(); zip.addLocalFolder(sourceFolder); // Strip external file attributes from every entry. `addLocalFolder` copies // the source's Unix mode bits onto each entry, so a directory with e.g. // `0500` on a CI checkout ends up in the bundle and makes `zip4j` on // Android fail with "Could not create directory" when extracting children // into that read-only parent. Clearing attrs lets the extractor fall back // to its OS defaults. Mirrors the plugin-side workaround in live-update // 8.2.1+ (`FileHeader.setExternalFileAttributes(null)`). for (const entry of zip.getEntries()) { entry.attr = 0; } return zip.toBuffer(); } async zipFolderWithGitignore(sourceFolder) { // Do NOT apply the `entry.attr = 0` workaround from `zipFolder` here. // This method zips full project sources for server-side builds (callers: // `apps:builds:create`, `apps:liveupdates:create`), which include // executables like `gradlew` whose `0755` mode must survive the round-trip // so the build runner can execute them. const files = await globby(['**/*'], { cwd: sourceFolder, gitignore: true, ignore: [ '.git/**', '**/node_modules/**', '**/ios/DerivedData/**', '**/ios/Pods/**', '**/ios/build/**', '**/android/build/**', '**/android/.gradle/**', '**/android/app/build/**', ], dot: true, }); if (files.length > MAX_ZIP_ENTRIES) { throw new UserError(`The source folder contains ${files.length} files, which exceeds the ZIP limit of ${MAX_ZIP_ENTRIES} entries. ` + `Make sure your .gitignore excludes large directories such as node_modules.`); } const zip = new AdmZip(); for (const file of files) { const filePath = path.join(sourceFolder, file); const dirName = path.dirname(file); zip.addLocalFile(filePath, dirName === '.' ? '' : dirName); } return zip.toBuffer(); } isZipped(filePath) { return filePath.endsWith('.zip'); } } const zip = new ZipImpl(); export default zip;