node.jsnode-archiver

Nodejs Archiver ArchiverError: archive already finalizing


I want to zip folders excluding certain files/folders so I used the solution in this answer. The solution works for a single folder but throws error when there are multiple folders to be zipped.

I need to make zips from each sub-folders of the source directory

Rootfolder:
 |-folder1
 |-folder2
 |-folder3

should result in:

build:
 |-{timeFormat}_folder1.zip
 |-{timeFormat}_folder2.zip
 |-{timeFormat}_folder3.zip

I am getting following error:

".../node_modules/archiver/lib/core.js:778
    var finalizingError = new ArchiverError('FINALIZING');
                          ^
ArchiverError: archive already finalizing
...
 at processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'FINALIZING',
  data: undefined
}"

My code is as follows:

const zipFolders = async (
  rootPath: string,
  dirPaths: string[]
): Promise<void> => {
  for await (const folder of dirPaths) {
    await makeZip(folder, rootPath);
  }
};

.........

const fs = require("fs");
const archiver = require("archiver");
const archive = archiver("zip");
import { format } from "date-fns";

const exclude =["assets/**","**/*.json"]

export const makeZip = (srcFolder: string, rootPath: string): Promise<void> =>
  new Promise((resolve) => {
    const timestamp = format(new Date(), "MM-DD-YYYY_HH-mm-ssZZ");
    const dirParts = srcFolder.split("/");
    const dirName = dirParts[dirParts.length - 1];
    const zipName = `${timestamp}_${dirName}`;
    const zipPath = `${rootPath}/build/${zipName}.zip`;


    const output = fs.createWriteStream(zipPath);
    output.on("close", function () {
      console.log("done writing: " + archive.pointer() + " total bytes");
      resolve();
    });
    archive.pipe(output);

    archive.on("error", function (err: Error) {
      throw err;
    });

    archive.glob("**/*", {
      cwd: srcFolder,
      ignore: exclude,
    });

    archive.finalize();
  });

I need some help regarding what needs to be updated or if there is any other way of achieving the same thing. Thank you.


Solution

  • Posting the solution I ended up using.

    const exclude = ["assets/**", "**/*.json"];
    
    const makeZip = (srcFolder: string, rootPath: string): Promise<void> =>
      new Promise((resolve, reject) => {
        const timestamp = format(new Date(), "MM-DD-YYYY_HH-mm-ssZZ");
        const dirParts = srcFolder.split("/");
        const dirName = dirParts[dirParts.length - 1];
        const zipName = `${timestamp}_${dirName}`;
        const zipPath = `${rootPath}/build/${zipName}.zip`;
    
        const archive = archiver("zip");
        const output = fs.createWriteStream(zipPath);
    
        output.on("close", function () {
          console.log("done writing: " + archive.pointer() + " total bytes");
          resolve();
        });
    
        archive.on("error", function (err: Error) {
          reject(err);
        });
    
        archive.glob("**/*", {
          cwd: srcFolder,
          ignore: exclude,
        });
    
        archive.pipe(output);
        archive.finalize();
      });
    

    ......

    const zipFolders = async (rootPath: string, dirPaths: string[]): Promise<void> => {
      const promises = dirPaths.map((folder) => makeZip(folder, rootPath));
      await Promise.all(promises);
    };