From 1a04257a10a93b086c2d272d2139ca71700c1800 Mon Sep 17 00:00:00 2001 From: Wilson Date: Fri, 6 Mar 2026 15:27:30 +0800 Subject: [PATCH] Move zipResults to utils/zipResults and update imports --- src/mergeAxeResults.ts | 2 +- src/utils.ts | 54 -------------------------------------- src/utils/index.ts | 1 + src/utils/zipResults.ts | 58 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 55 deletions(-) create mode 100644 src/utils/zipResults.ts diff --git a/src/mergeAxeResults.ts b/src/mergeAxeResults.ts index 9ce3c052..c990df01 100644 --- a/src/mergeAxeResults.ts +++ b/src/mergeAxeResults.ts @@ -28,7 +28,6 @@ import { getBrowserToRun, getPlaywrightLaunchOptions } from './constants/common. import { getWcagPassPercentage, getProgressPercentage, - zipResults, getIssuesPercentage, getWcagCriteriaMap, categorizeWcagCriteria, @@ -40,6 +39,7 @@ import { getUserDataTxt, getVersion, retryFunction, + zipResults, } from './utils/index.js'; import { consoleLogger, silentLogger } from './logs.js'; import itemTypeDescription from './constants/itemTypeDescription.js'; diff --git a/src/utils.ts b/src/utils.ts index 6005531f..edfb526d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,6 @@ import path from 'path'; import fs from 'fs-extra'; import axe, { Rule } from 'axe-core'; -import JSZip from 'jszip'; -import { createReadStream, createWriteStream } from 'fs'; import constants from './constants/constants.js'; import { consoleLogger, errorsTxtPath } from './logs.js'; import { getAxeConfiguration } from './crawlers/custom/getAxeConfiguration.js'; @@ -763,58 +761,6 @@ export const getIssuesPercentage = async ( }; }; -export const zipResults = async (zipName: string, resultsPath: string): Promise => { - // Resolve and validate the output path - const zipFilePath = path.isAbsolute(zipName) ? zipName : path.join(resultsPath, zipName); - - // Ensure parent dir exists - fs.mkdirSync(path.dirname(zipFilePath), { recursive: true }); - - // Remove any prior file atomically - try { - fs.unlinkSync(zipFilePath); - } catch { - /* ignore if not exists */ - } - - // CWD must exist and be a directory - const stats = fs.statSync(resultsPath); - if (!stats.isDirectory()) { - throw new Error(`resultsPath is not a directory: ${resultsPath}`); - } - async function addFolderToZip(folderPath: string, zipFolder: JSZip): Promise { - const items = await fs.readdir(folderPath); - for (const item of items) { - const fullPath = path.join(folderPath, item); - const stats = await fs.stat(fullPath); - if (stats.isDirectory()) { - const folder = zipFolder.folder(item); - await addFolderToZip(fullPath, folder); - } else { - // Add file as a stream so that it doesn't load the entire file into memory - zipFolder.file(item, createReadStream(fullPath)); - } - } - } - - const zip = new JSZip(); - await addFolderToZip(resultsPath, zip); - - const zipStream = zip.generateNodeStream({ - type: 'nodebuffer', - streamFiles: true, - compression: 'DEFLATE', - }); - - await new Promise((resolve, reject) => { - const outStream = createWriteStream(zipFilePath); - zipStream - .pipe(outStream) - .on('finish', () => resolve(undefined)) - .on('error', reject); - }); -}; - /** * Determines which WCAG criteria might appear in the "needsReview" category * based on axe-core's rule configuration. diff --git a/src/utils/index.ts b/src/utils/index.ts index 75688744..6f13cf44 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -6,6 +6,7 @@ export { default as getStoragePath } from './getStoragePath.js'; export { default as getPdfStoragePath } from './getPdfStoragePath.js'; export { default as isWhitelistedContentType } from './isWhitelistedContentType.js'; export { default as retryFunction } from './retryFunction.js'; +export { default as zipResults } from './zipResults.js'; export { default as randomThreeDigitNumberString } from './randomThreeDigitNumberString.js'; export { areLinksEqual, isFollowStrategy } from './linkStrategy.js'; export { setHeadlessMode, setThresholdLimits } from './runtimeFlags.js'; diff --git a/src/utils/zipResults.ts b/src/utils/zipResults.ts new file mode 100644 index 00000000..6f3e50f6 --- /dev/null +++ b/src/utils/zipResults.ts @@ -0,0 +1,58 @@ +import path from 'path'; +import fs from 'fs-extra'; +import JSZip from 'jszip'; +import { createReadStream, createWriteStream } from 'fs'; + +const zipResults = async (zipName: string, resultsPath: string): Promise => { + // Resolve and validate the output path + const zipFilePath = path.isAbsolute(zipName) ? zipName : path.join(resultsPath, zipName); + + // Ensure parent dir exists + fs.mkdirSync(path.dirname(zipFilePath), { recursive: true }); + + // Remove any prior file atomically + try { + fs.unlinkSync(zipFilePath); + } catch { + /* ignore if not exists */ + } + + // CWD must exist and be a directory + const stats = fs.statSync(resultsPath); + if (!stats.isDirectory()) { + throw new Error(`resultsPath is not a directory: ${resultsPath}`); + } + async function addFolderToZip(folderPath: string, zipFolder: JSZip): Promise { + const items = await fs.readdir(folderPath); + for (const item of items) { + const fullPath = path.join(folderPath, item); + const stats = await fs.stat(fullPath); + if (stats.isDirectory()) { + const folder = zipFolder.folder(item); + await addFolderToZip(fullPath, folder); + } else { + // Add file as a stream so that it doesn't load the entire file into memory + zipFolder.file(item, createReadStream(fullPath)); + } + } + } + + const zip = new JSZip(); + await addFolderToZip(resultsPath, zip); + + const zipStream = zip.generateNodeStream({ + type: 'nodebuffer', + streamFiles: true, + compression: 'DEFLATE', + }); + + await new Promise((resolve, reject) => { + const outStream = createWriteStream(zipFilePath); + zipStream + .pipe(outStream) + .on('finish', () => resolve(undefined)) + .on('error', reject); + }); +}; + +export default zipResults;