diff --git a/gulpfile.mjs b/gulpfile.mjs index 01d715e0e..9b3e43890 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -736,7 +736,7 @@ function runTests(testsName, { bot = false, xfaOnly = false } = {}) { } if (process.argv.includes("--coverage-output")) { args.push( - "--coverage-output", + "--coverageOutput", process.argv[process.argv.indexOf("--coverage-output") + 1] ); } diff --git a/package-lock.json b/package-lock.json index a534df66b..0d4d6089e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,8 +70,7 @@ "typescript": "^5.9.3", "vinyl": "^3.0.1", "webpack": "^5.105.2", - "webpack-stream": "^7.0.0", - "yargs": "^18.0.0" + "webpack-stream": "^7.0.0" }, "engines": { "node": ">=20.19.0 || >=22.13.0 || >=24" @@ -108,6 +107,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1647,6 +1647,7 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -1688,6 +1689,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1728,6 +1730,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" } @@ -3097,6 +3100,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -3161,6 +3165,7 @@ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -3587,6 +3592,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4242,7 +4248,8 @@ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.7.0.tgz", "integrity": "sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA==", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/bare-fs": { "version": "4.5.4", @@ -4478,6 +4485,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5054,77 +5062,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", - "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -5738,7 +5675,8 @@ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1566079.tgz", "integrity": "sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/dir-glob": { "version": "3.0.1", @@ -6275,6 +6213,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6335,6 +6274,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -7729,6 +7669,7 @@ "integrity": "sha512-PErok3DZSA5WGMd6XXV3IRNO0mlB+wW3OzhFJLEec1jSERg2j1bxJ6e5Fh6N6fn3FH2T9AP4UYNb/pYlADB9sA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob-watcher": "^6.0.0", "gulp-cli": "^3.1.0", @@ -9810,6 +9751,7 @@ "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -9951,6 +9893,7 @@ "integrity": "sha512-DkoXO1jz0UY+k1tj1LpxYLrN+jeGKBicbtsQYeYF8nX9QK4AGyGh4g421qsmEOGfZ02GjW1qxr1XP+8afwcTGQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.3", "commander": "^11.1.0", @@ -11044,6 +10987,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -11196,6 +11140,7 @@ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11248,6 +11193,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -12124,6 +12070,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -13889,6 +13836,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -14142,6 +14090,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14528,6 +14477,7 @@ "integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -15139,24 +15089,6 @@ "node": ">= 14.6" } }, - "node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, "node_modules/yargs-parser": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", @@ -15167,31 +15099,6 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", - "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 63b754926..5fe96e2ed 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,7 @@ "typescript": "^5.9.3", "vinyl": "^3.0.1", "webpack": "^5.105.2", - "webpack-stream": "^7.0.0", - "yargs": "^18.0.0" + "webpack-stream": "^7.0.0" }, "repository": { "type": "git", diff --git a/test/stats/statcmp.js b/test/stats/statcmp.js index be8cfc9c1..f3d4f80e7 100644 --- a/test/stats/statcmp.js +++ b/test/stats/statcmp.js @@ -2,6 +2,7 @@ import { createRequire } from "module"; import fs from "fs"; +import { parseArgs } from "node:util"; const require = createRequire(import.meta.url); const ttest = require("ttest"); @@ -9,26 +10,28 @@ const ttest = require("ttest"); const VALID_GROUP_BYS = ["browser", "pdf", "page", "round", "stat"]; function parseOptions() { - const yargs = require("yargs") - .usage( + const { values, positionals } = parseArgs({ + args: process.argv.slice(2), + allowPositionals: true, + options: { + groupBy: { type: "string", default: "browser,stat" }, + }, + }); + + if (positionals.length < 2) { + console.error( "Compare the results of two stats files.\n" + - "Usage:\n $0 [options]" - ) - .demand(2) - .string(["groupBy"]) - .describe( - "groupBy", - "How statistics should grouped. Valid options: " + - VALID_GROUP_BYS.join(" ") - ) - .default("groupBy", "browser,stat"); - const result = yargs.argv; - result.baseline = result._[0]; - result.current = result._[1]; - if (result.groupBy) { - result.groupBy = result.groupBy.split(/[;, ]+/); + "Usage:\n statcmp.js [--groupBy=]\n\n" + + ` --groupBy How statistics should be grouped. Valid options: ${VALID_GROUP_BYS.join(" ")}. [browser,stat]` + ); + process.exit(1); } - return result; + + return { + baseline: positionals[0], + current: positionals[1], + groupBy: values.groupBy.split(/[;, ]+/), + }; } function group(stats, groupBy) { diff --git a/test/test.mjs b/test/test.mjs index a32106401..7dd726c6c 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -25,184 +25,104 @@ import istanbulCoverage from "istanbul-lib-coverage"; import istanbulReportGenerator from "istanbul-reports"; import libReport from "istanbul-lib-report"; import os from "os"; +import { parseArgs } from "node:util"; import path from "path"; import puppeteer from "puppeteer"; import readline from "readline"; import { translateFont } from "./font/ttxdriver.mjs"; import { WebServer } from "./webserver.mjs"; -import yargs from "yargs"; const __dirname = import.meta.dirname; function parseOptions() { - const parsedArgs = yargs(process.argv) - .usage("Usage: $0") - .option("downloadOnly", { - default: false, - describe: "Download test PDFs without running the tests.", - type: "boolean", - }) - .option("fontTest", { - default: false, - describe: "Run the font tests.", - type: "boolean", - }) - .option("help", { - alias: "h", - default: false, - describe: "Show this help message.", - type: "boolean", - }) - .option("integration", { - default: false, - describe: "Run the integration tests.", - type: "boolean", - }) - .option("manifestFile", { - default: "test_manifest.json", - describe: "A path to JSON file in the form of `test_manifest.json`.", - type: "string", - }) - .option("masterMode", { - alias: "m", - default: false, - describe: "Run the script in master mode.", - type: "boolean", - }) - .option("noChrome", { - default: false, - describe: "Skip Chrome when running tests.", - type: "boolean", - }) - .option("noFirefox", { - default: false, - describe: "Skip Firefox when running tests.", - type: "boolean", - }) - .option("noDownload", { - default: false, - describe: "Skip downloading of test PDFs.", - type: "boolean", - }) - .option("noPrompts", { - default: false, - describe: "Uses default answers (intended for CLOUD TESTS only!).", - type: "boolean", - }) - .option("headless", { - default: false, - describe: - "Run the tests in headless mode, i.e. without visible browser windows.", - type: "boolean", - }) - .option("port", { - default: 0, - describe: "The port the HTTP server should listen on.", - type: "number", - }) - .option("reftest", { - default: false, - describe: - "Automatically start reftest showing comparison test failures, if there are any.", - type: "boolean", - }) - .option("statsDelay", { - default: 0, - describe: - "The amount of time in milliseconds the browser should wait before starting stats.", - type: "number", - }) - .option("statsFile", { - default: "", - describe: "The file where to store stats.", - type: "string", - }) - .option("strictVerify", { - default: false, - describe: "Error if verifying the manifest files fails.", - type: "boolean", - }) - .option("coverage", { - default: false, - describe: "Enable code coverage collection.", - type: "boolean", - }) - .option("coverageOutput", { - default: "build/coverage", - describe: "The directory where to store code coverage data.", - type: "string", - }) - .option("testfilter", { - alias: "t", - default: [], - describe: "Run specific reftest(s).", - type: "array", - }) - .example( - "testfilter", - "$0 -t=issue5567 -t=issue5909\n" + - "Run the reftest identified by issue5567 and issue5909." - ) - .option("unitTest", { - default: false, - describe: "Run the unit tests.", - type: "boolean", - }) - .option("xfaOnly", { - default: false, - describe: "Only run the XFA reftest(s).", - type: "boolean", - }) - .check(argv => { - if ( - +argv.reftest + argv.unitTest + argv.fontTest + argv.masterMode <= - 1 - ) { - return true; - } - throw new Error( - "--reftest, --unitTest, --fontTest, and --masterMode must not be specified together." - ); - }) - .check(argv => { - if ( - +argv.unitTest + argv.fontTest + argv.integration + argv.xfaOnly <= - 1 - ) { - return true; - } - throw new Error( - "--unitTest, --fontTest, --integration, and --xfaOnly must not be specified together." - ); - }) - .check(argv => { - if (argv.testfilter?.length > 0 && argv.xfaOnly) { - throw new Error("--testfilter and --xfaOnly cannot be used together."); - } - return true; - }) - .check(argv => { - if (!argv.noDownload || !argv.downloadOnly) { - return true; - } - throw new Error( - "--noDownload and --downloadOnly cannot be used together." - ); - }) - .check(argv => { - if (!argv.masterMode || argv.manifestFile === "test_manifest.json") { - return true; - } - throw new Error( - "when --masterMode is specified --manifestFile shall be equal to `test_manifest.json`." - ); - }); + const { values } = parseArgs({ + args: process.argv.slice(2), + options: { + coverage: { type: "boolean", default: false }, + coverageOutput: { type: "string", default: "build/coverage" }, + downloadOnly: { type: "boolean", default: false }, + fontTest: { type: "boolean", default: false }, + headless: { type: "boolean", default: false }, + help: { type: "boolean", short: "h", default: false }, + integration: { type: "boolean", default: false }, + manifestFile: { type: "string", default: "test_manifest.json" }, + masterMode: { type: "boolean", short: "m", default: false }, + noChrome: { type: "boolean", default: false }, + noDownload: { type: "boolean", default: false }, + noFirefox: { type: "boolean", default: false }, + noPrompts: { type: "boolean", default: false }, + port: { type: "string", default: "0" }, + reftest: { type: "boolean", default: false }, + statsDelay: { type: "string", default: "0" }, + statsFile: { type: "string", default: "" }, + strictVerify: { type: "boolean", default: false }, + testfilter: { type: "string", short: "t", multiple: true, default: [] }, + unitTest: { type: "boolean", default: false }, + xfaOnly: { type: "boolean", default: false }, + }, + }); - const result = parsedArgs.argv; - result.testfilter = Array.isArray(result.testfilter) - ? result.testfilter - : [result.testfilter]; - return result; + if (values.help) { + console.log( + "Usage: test.mjs\n\n" + + " --coverage Enable code coverage collection.\n" + + " --coverageOutput Directory for code coverage data. [build/coverage]\n" + + " --downloadOnly Download test PDFs without running the tests.\n" + + " --fontTest Run the font tests.\n" + + " --headless Run tests without visible browser windows.\n" + + " --help, -h Show this help message.\n" + + " --integration Run the integration tests.\n" + + " --manifestFile Path to manifest JSON file. [test_manifest.json]\n" + + " --masterMode, -m Run the script in master mode.\n" + + " --noChrome Skip Chrome when running tests.\n" + + " --noDownload Skip downloading of test PDFs.\n" + + " --noFirefox Skip Firefox when running tests.\n" + + " --noPrompts Use default answers (for CLOUD TESTS only!).\n" + + " --port Port for the HTTP server. [0]\n" + + " --reftest Start reftest viewer on comparison failures.\n" + + " --statsDelay Milliseconds to wait before starting stats. [0]\n" + + " --statsFile File where to store stats.\n" + + " --strictVerify Error if manifest file verification fails.\n" + + " --testfilter, -t Run specific reftest(s), e.g. -t=issue5567.\n" + + " --unitTest Run the unit tests.\n" + + " --xfaOnly Only run the XFA reftest(s)." + ); + process.exit(0); + } + + if ( + +values.reftest + values.unitTest + values.fontTest + values.masterMode > + 1 + ) { + throw new Error( + "--reftest, --unitTest, --fontTest, and --masterMode must not be specified together." + ); + } + if ( + +values.unitTest + values.fontTest + values.integration + values.xfaOnly > + 1 + ) { + throw new Error( + "--unitTest, --fontTest, --integration, and --xfaOnly must not be specified together." + ); + } + if (values.testfilter.length > 0 && values.xfaOnly) { + throw new Error("--testfilter and --xfaOnly cannot be used together."); + } + if (values.noDownload && values.downloadOnly) { + throw new Error("--noDownload and --downloadOnly cannot be used together."); + } + if (values.masterMode && values.manifestFile !== "test_manifest.json") { + throw new Error( + "when --masterMode is specified --manifestFile shall be equal to `test_manifest.json`." + ); + } + + return { + ...values, + port: parseInt(values.port, 10) || 0, + statsDelay: parseInt(values.statsDelay, 10) || 0, + }; } var refsTmpDir = "tmp";