├── .gitignore ├── .npmrc ├── README.md ├── bench-it.js ├── console-output.js ├── fixtures ├── .env.sample ├── lodash.fp.js └── ts-sample.ts ├── index.js ├── package.json ├── pnpm-lock.yaml ├── src ├── babel-benchmark.js ├── dotenv-benchmark.js ├── fastify-benchmark-disabled.js ├── fastify-server.js ├── lodash-benchmark.js ├── moment-benchmark.js ├── pino-benchmark.js ├── prettier-benchmark.js ├── typescript-benchmark.js ├── underscore-benchmark.js └── winston-benchmark.js └── worker.js /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | .pnpm-debug.log* 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # Snowpack dependency directory (https://snowpack.dev/) 48 | web_modules/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional stylelint cache 60 | .stylelintcache 61 | 62 | # Microbundle cache 63 | .rpt2_cache/ 64 | .rts2_cache_cjs/ 65 | .rts2_cache_es/ 66 | .rts2_cache_umd/ 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # Output of 'npm pack' 72 | *.tgz 73 | 74 | # Yarn Integrity file 75 | .yarn-integrity 76 | 77 | # dotenv environment variable files 78 | .env 79 | .env.development.local 80 | .env.test.local 81 | .env.production.local 82 | .env.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | out 91 | 92 | # Nuxt.js build / generate output 93 | .nuxt 94 | dist 95 | 96 | # Gatsby files 97 | .cache/ 98 | # Comment in the public line in if your project uses Gatsby and not Next.js 99 | # https://nextjs.org/blog/next-9-1#public-directory-support 100 | # public 101 | 102 | # vuepress build output 103 | .vuepress/dist 104 | 105 | # vuepress v2.x temp and cache directory 106 | .temp 107 | .cache 108 | 109 | # Docusaurus cache and generated files 110 | .docusaurus 111 | 112 | # Serverless directories 113 | .serverless/ 114 | 115 | # FuseBox cache 116 | .fusebox/ 117 | 118 | # DynamoDB Local files 119 | .dynamodb/ 120 | 121 | # TernJS port file 122 | .tern-port 123 | 124 | # Stores VSCode versions used for testing VSCode extensions 125 | .vscode-test 126 | 127 | # yarn v2 128 | .yarn/cache 129 | .yarn/unplugged 130 | .yarn/build-state.yml 131 | .yarn/install-state.gz 132 | .pnp.* 133 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # We use save-exact because the purpose of this 2 | # repository is to find regressions, if we pull 3 | # a new version of each package the results will not be consistent 4 | save-exact=true 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nodejs-package-benchmark 2 | 3 | This package allows you to benchmark different runtimes using popular 4 | packages operations. 5 | 6 | ## Supported packages 7 | 8 | - [x] ~fastify~ - Temporary disabled. 9 | - [x] lodash 10 | - [x] prettier 11 | - [x] babel 12 | - [x] moment 13 | - [x] dotenv 14 | - [x] pinojs 15 | - [x] winston 16 | - [x] underscore 17 | - [x] typescript 18 | 19 | ## Install 20 | 21 | ```console 22 | npm i -g nodejs-package-benchmark 23 | ``` 24 | 25 | ## Comparison 26 | 27 | To compare binaries, you can use the `bench-it` script. 28 | 29 | ### Syntax: `bench-it $BINARY ["baseline"]` 30 | 31 | This script allows you to compare the performance of binaries. If it's your first run, you need to generate the `baseline` data using: 32 | 33 | ```console 34 | $ bench-it ./node baseline 35 | ``` 36 | 37 | To compare subsequent runs, simply omit the "baseline" option: 38 | 39 | ```console 40 | $ bench-it ./node 41 | ``` 42 | > [!TIP] 43 | > It's recommended to have `colordiff` installed for a clearer comparison of differences. 44 | 45 | ## Single run 46 | 47 | To a pretty terminal output, run `index.js` 48 | 49 | ```console 50 | $ node --allow-natives-syntax index.js 51 | cpu: 13th Gen Intel(R) Core(TM) i5-13600K (20 cores) 52 | node: v20.13.1 (/home/hzk/.nvm/versions/node/v20.13.1/bin/node) 53 | os: Linux 5.15.133.1-microsoft-standard-WSL2 x64 54 | --------------------------------------------------------------------- 55 | babel 56 | transform (code=true ast=true): 147.1 (15 samples) 57 | transform (code=false): 150.4 (16 samples) 58 | dotenv 59 | config: 64.39K (6440 samples) 60 | lodash 61 | .chunk: 19.62M (1961973 samples) 62 | .groupBy: 6.303M (630542 samples) 63 | .includes: 18.38M (1837801 samples) 64 | .orderBy: 1.737M (173672 samples) 65 | moment 66 | format (full): 878.8K (87908 samples) 67 | format: 839.3K (83928 samples) 68 | fromNow (YYYYMMDD): 153.4K (15339 samples) 69 | subtract (10): 288.7K (28871 samples) 70 | pinojs 71 | info (10x): 243.7K (24686 samples) 72 | prettier 73 | format: 71.71 (10 samples) 74 | format (singleQuote=true useTabs=true): 68.52 (10 samples) 75 | format (semi=false): 70.61 (10 samples) 76 | typescript 77 | transpile: 85.23 (10 samples) 78 | createSourceFile: 1.866K (187 samples) 79 | getSemanticDiagnostics: 2.102 (10 samples) 80 | underscore 81 | .chunk: 4.606M (467160 samples) 82 | .groupBy: 1.66M (169265 samples) 83 | .includes: 7.626M (762632 samples) 84 | .orderBy: 733.5K (73352 samples) 85 | winston 86 | info (10x): 43.13K (4431 samples) 87 | --------------------------------------------------------------------- 88 | ``` 89 | 90 | To store it as JSON, just pipe output to a file: 91 | 92 | ```console 93 | $ node index.js > results.json 94 | $ cat result.json 95 | [ 96 | { 97 | "name": "babel", 98 | "method": "benchmarkjs", 99 | "operations": [ 100 | { 101 | "name": "transform (code=true ast=true)", 102 | "opsSec": 67.80076532539411, 103 | "samples": 3 104 | }, 105 | { 106 | ... 107 | ``` 108 | -------------------------------------------------------------------------------- /bench-it.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { execSync } = require('child_process'); 4 | const fs = require('fs'); 5 | 6 | const NODEJS_PACKAGE_BENCHMARK_PATH = __dirname; 7 | 8 | if (process.argv.length < 3) { 9 | console.log("You must pass the binary as argument. Example: bench-it ./node"); 10 | process.exit(1); 11 | } 12 | 13 | const BINARY = process.argv[2]; 14 | 15 | if (process.argv[3] === "baseline") { 16 | const result = execSync(`${BINARY} --allow-natives-syntax ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { 17 | env: { TTY: true }, 18 | }).toString(); 19 | fs.writeFileSync('baseline.out', `${result}`); 20 | console.log("Baseline generated."); 21 | process.exit(0); 22 | } 23 | 24 | if (!fs.existsSync('./baseline.out')) { 25 | console.log(`The baseline.out does not exist. Generate it with: $ bench-it ${BINARY} baseline.`); 26 | process.exit(1); 27 | } 28 | 29 | let diffCmd = "colordiff"; 30 | try { 31 | execSync("command -v colordiff"); 32 | } catch (error) { 33 | console.log("⚠️ 'colordiff' was not found. Using 'diff' as fallback."); 34 | diffCmd = "diff"; 35 | } 36 | 37 | const currentResult = execSync(`${BINARY} --allow-natives-syntax ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { 38 | env: { TTY: true }, 39 | }).toString(); 40 | fs.writeFileSync('current.out', currentResult); 41 | 42 | try { 43 | const stdout = execSync(`${diffCmd} -y baseline.out current.out`, { 44 | cwd: process.cwd() 45 | }) 46 | console.log(stdout.toString()) 47 | } catch (e) { 48 | // `diff` returns a non-0 exit code 49 | console.log(e.message) 50 | console.log(e.stdout.toString()) 51 | } 52 | -------------------------------------------------------------------------------- /console-output.js: -------------------------------------------------------------------------------- 1 | const opsSecFormatter = Intl.NumberFormat('en-US', { 2 | notation: 'compact', 3 | maximumSignificantDigits: 4 4 | }); 5 | 6 | const halfScreen = process.stdout.columns ? process.stdout.columns / 2 : 44; // arbitrary number 7 | 8 | module.exports = { 9 | info(str) { 10 | console.log(str); 11 | }, 12 | start() { 13 | console.log('-'.repeat(halfScreen)); 14 | }, 15 | end() { 16 | console.log('-'.repeat(halfScreen)); 17 | }, 18 | step(result) { 19 | console.log(`${result.name}`); 20 | // TODO(rafaelgss): support non-operation method 21 | for (const operation of result.operations) { 22 | const opName = ` ${operation.name}:`; 23 | let spaces = ''; 24 | 25 | if (opName.length > halfScreen) { 26 | spaces = opName.length + 2; 27 | } else { 28 | spaces = ' '.repeat(halfScreen - opName.length); 29 | } 30 | 31 | console.log( 32 | `${opName}${spaces}${opsSecFormatter.format(operation.opsSec)} (${ 33 | operation.samples 34 | } samples)` 35 | ); 36 | } 37 | }, 38 | printResults() {} 39 | }; 40 | -------------------------------------------------------------------------------- /fixtures/.env.sample: -------------------------------------------------------------------------------- 1 | # Database Configuration 2 | DB_HOST=localhost 3 | DB_PORT=5432 4 | DB_USERNAME=myusername 5 | DB_PASSWORD=mypassword 6 | DB_NAME=mydatabase 7 | 8 | # API Keys 9 | API_KEY_1=your_api_key_1 10 | API_KEY_2=your_api_key_2 11 | API_KEY_3=your_api_key_3 12 | 13 | # Server Configuration 14 | SERVER_HOST=127.0.0.1 15 | SERVER_PORT=8080 16 | 17 | # Logging Configuration 18 | LOG_LEVEL=debug 19 | LOG_PATH=/var/log/myapp.log 20 | 21 | # Authentication 22 | JWT_SECRET=your_jwt_secret 23 | OAUTH_CLIENT_ID=your_oauth_client_id 24 | OAUTH_CLIENT_SECRET=your_oauth_client_secret 25 | 26 | # Email Configuration 27 | EMAIL_HOST=smtp.example.com 28 | EMAIL_PORT=587 29 | EMAIL_USERNAME=myemail@example.com 30 | EMAIL_PASSWORD=myemailpassword 31 | EMAIL_FROM=myemail@example.com 32 | 33 | # AWS Configuration 34 | AWS_ACCESS_KEY_ID=your_aws_access_key_id 35 | AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key 36 | AWS_REGION=us-east-1 37 | S3_BUCKET=my-s3-bucket 38 | 39 | # Miscellaneous 40 | DEBUG_MODE=true 41 | CACHE_ENABLED=true 42 | -------------------------------------------------------------------------------- /fixtures/lodash.fp.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define([], factory); 6 | else if(typeof exports === 'object') 7 | exports["fp"] = factory(); 8 | else 9 | root["fp"] = factory(); 10 | })(this, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) 20 | /******/ return installedModules[moduleId].exports; 21 | 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ exports: {}, 25 | /******/ id: moduleId, 26 | /******/ loaded: false 27 | /******/ }; 28 | 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | 32 | /******/ // Flag the module as loaded 33 | /******/ module.loaded = true; 34 | 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | 39 | 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | 46 | /******/ // __webpack_public_path__ 47 | /******/ __webpack_require__.p = ""; 48 | 49 | /******/ // Load entry module and return exports 50 | /******/ return __webpack_require__(0); 51 | /******/ }) 52 | /************************************************************************/ 53 | /******/ ([ 54 | /* 0 */ 55 | /***/ (function(module, exports, __webpack_require__) { 56 | 57 | var baseConvert = __webpack_require__(1); 58 | 59 | /** 60 | * Converts `lodash` to an immutable auto-curried iteratee-first data-last 61 | * version with conversion `options` applied. 62 | * 63 | * @param {Function} lodash The lodash function to convert. 64 | * @param {Object} [options] The options object. See `baseConvert` for more details. 65 | * @returns {Function} Returns the converted `lodash`. 66 | */ 67 | function browserConvert(lodash, options) { 68 | return baseConvert(lodash, lodash, options); 69 | } 70 | 71 | if (typeof _ == 'function' && typeof _.runInContext == 'function') { 72 | _ = browserConvert(_.runInContext()); 73 | } 74 | module.exports = browserConvert; 75 | 76 | 77 | /***/ }), 78 | /* 1 */ 79 | /***/ (function(module, exports, __webpack_require__) { 80 | 81 | var mapping = __webpack_require__(2), 82 | fallbackHolder = __webpack_require__(3); 83 | 84 | /** Built-in value reference. */ 85 | var push = Array.prototype.push; 86 | 87 | /** 88 | * Creates a function, with an arity of `n`, that invokes `func` with the 89 | * arguments it receives. 90 | * 91 | * @private 92 | * @param {Function} func The function to wrap. 93 | * @param {number} n The arity of the new function. 94 | * @returns {Function} Returns the new function. 95 | */ 96 | function baseArity(func, n) { 97 | return n == 2 98 | ? function(a, b) { return func.apply(undefined, arguments); } 99 | : function(a) { return func.apply(undefined, arguments); }; 100 | } 101 | 102 | /** 103 | * Creates a function that invokes `func`, with up to `n` arguments, ignoring 104 | * any additional arguments. 105 | * 106 | * @private 107 | * @param {Function} func The function to cap arguments for. 108 | * @param {number} n The arity cap. 109 | * @returns {Function} Returns the new function. 110 | */ 111 | function baseAry(func, n) { 112 | return n == 2 113 | ? function(a, b) { return func(a, b); } 114 | : function(a) { return func(a); }; 115 | } 116 | 117 | /** 118 | * Creates a clone of `array`. 119 | * 120 | * @private 121 | * @param {Array} array The array to clone. 122 | * @returns {Array} Returns the cloned array. 123 | */ 124 | function cloneArray(array) { 125 | var length = array ? array.length : 0, 126 | result = Array(length); 127 | 128 | while (length--) { 129 | result[length] = array[length]; 130 | } 131 | return result; 132 | } 133 | 134 | /** 135 | * Creates a function that clones a given object using the assignment `func`. 136 | * 137 | * @private 138 | * @param {Function} func The assignment function. 139 | * @returns {Function} Returns the new cloner function. 140 | */ 141 | function createCloner(func) { 142 | return function(object) { 143 | return func({}, object); 144 | }; 145 | } 146 | 147 | /** 148 | * A specialized version of `_.spread` which flattens the spread array into 149 | * the arguments of the invoked `func`. 150 | * 151 | * @private 152 | * @param {Function} func The function to spread arguments over. 153 | * @param {number} start The start position of the spread. 154 | * @returns {Function} Returns the new function. 155 | */ 156 | function flatSpread(func, start) { 157 | return function() { 158 | var length = arguments.length, 159 | lastIndex = length - 1, 160 | args = Array(length); 161 | 162 | while (length--) { 163 | args[length] = arguments[length]; 164 | } 165 | var array = args[start], 166 | otherArgs = args.slice(0, start); 167 | 168 | if (array) { 169 | push.apply(otherArgs, array); 170 | } 171 | if (start != lastIndex) { 172 | push.apply(otherArgs, args.slice(start + 1)); 173 | } 174 | return func.apply(this, otherArgs); 175 | }; 176 | } 177 | 178 | /** 179 | * Creates a function that wraps `func` and uses `cloner` to clone the first 180 | * argument it receives. 181 | * 182 | * @private 183 | * @param {Function} func The function to wrap. 184 | * @param {Function} cloner The function to clone arguments. 185 | * @returns {Function} Returns the new immutable function. 186 | */ 187 | function wrapImmutable(func, cloner) { 188 | return function() { 189 | var length = arguments.length; 190 | if (!length) { 191 | return; 192 | } 193 | var args = Array(length); 194 | while (length--) { 195 | args[length] = arguments[length]; 196 | } 197 | var result = args[0] = cloner.apply(undefined, args); 198 | func.apply(undefined, args); 199 | return result; 200 | }; 201 | } 202 | 203 | /** 204 | * The base implementation of `convert` which accepts a `util` object of methods 205 | * required to perform conversions. 206 | * 207 | * @param {Object} util The util object. 208 | * @param {string} name The name of the function to convert. 209 | * @param {Function} func The function to convert. 210 | * @param {Object} [options] The options object. 211 | * @param {boolean} [options.cap=true] Specify capping iteratee arguments. 212 | * @param {boolean} [options.curry=true] Specify currying. 213 | * @param {boolean} [options.fixed=true] Specify fixed arity. 214 | * @param {boolean} [options.immutable=true] Specify immutable operations. 215 | * @param {boolean} [options.rearg=true] Specify rearranging arguments. 216 | * @returns {Function|Object} Returns the converted function or object. 217 | */ 218 | function baseConvert(util, name, func, options) { 219 | var isLib = typeof name == 'function', 220 | isObj = name === Object(name); 221 | 222 | if (isObj) { 223 | options = func; 224 | func = name; 225 | name = undefined; 226 | } 227 | if (func == null) { 228 | throw new TypeError; 229 | } 230 | options || (options = {}); 231 | 232 | var config = { 233 | 'cap': 'cap' in options ? options.cap : true, 234 | 'curry': 'curry' in options ? options.curry : true, 235 | 'fixed': 'fixed' in options ? options.fixed : true, 236 | 'immutable': 'immutable' in options ? options.immutable : true, 237 | 'rearg': 'rearg' in options ? options.rearg : true 238 | }; 239 | 240 | var defaultHolder = isLib ? func : fallbackHolder, 241 | forceCurry = ('curry' in options) && options.curry, 242 | forceFixed = ('fixed' in options) && options.fixed, 243 | forceRearg = ('rearg' in options) && options.rearg, 244 | pristine = isLib ? func.runInContext() : undefined; 245 | 246 | var helpers = isLib ? func : { 247 | 'ary': util.ary, 248 | 'assign': util.assign, 249 | 'clone': util.clone, 250 | 'curry': util.curry, 251 | 'forEach': util.forEach, 252 | 'isArray': util.isArray, 253 | 'isError': util.isError, 254 | 'isFunction': util.isFunction, 255 | 'isWeakMap': util.isWeakMap, 256 | 'iteratee': util.iteratee, 257 | 'keys': util.keys, 258 | 'rearg': util.rearg, 259 | 'toInteger': util.toInteger, 260 | 'toPath': util.toPath 261 | }; 262 | 263 | var ary = helpers.ary, 264 | assign = helpers.assign, 265 | clone = helpers.clone, 266 | curry = helpers.curry, 267 | each = helpers.forEach, 268 | isArray = helpers.isArray, 269 | isError = helpers.isError, 270 | isFunction = helpers.isFunction, 271 | isWeakMap = helpers.isWeakMap, 272 | keys = helpers.keys, 273 | rearg = helpers.rearg, 274 | toInteger = helpers.toInteger, 275 | toPath = helpers.toPath; 276 | 277 | var aryMethodKeys = keys(mapping.aryMethod); 278 | 279 | var wrappers = { 280 | 'castArray': function(castArray) { 281 | return function() { 282 | var value = arguments[0]; 283 | return isArray(value) 284 | ? castArray(cloneArray(value)) 285 | : castArray.apply(undefined, arguments); 286 | }; 287 | }, 288 | 'iteratee': function(iteratee) { 289 | return function() { 290 | var func = arguments[0], 291 | arity = arguments[1], 292 | result = iteratee(func, arity), 293 | length = result.length; 294 | 295 | if (config.cap && typeof arity == 'number') { 296 | arity = arity > 2 ? (arity - 2) : 1; 297 | return (length && length <= arity) ? result : baseAry(result, arity); 298 | } 299 | return result; 300 | }; 301 | }, 302 | 'mixin': function(mixin) { 303 | return function(source) { 304 | var func = this; 305 | if (!isFunction(func)) { 306 | return mixin(func, Object(source)); 307 | } 308 | var pairs = []; 309 | each(keys(source), function(key) { 310 | if (isFunction(source[key])) { 311 | pairs.push([key, func.prototype[key]]); 312 | } 313 | }); 314 | 315 | mixin(func, Object(source)); 316 | 317 | each(pairs, function(pair) { 318 | var value = pair[1]; 319 | if (isFunction(value)) { 320 | func.prototype[pair[0]] = value; 321 | } else { 322 | delete func.prototype[pair[0]]; 323 | } 324 | }); 325 | return func; 326 | }; 327 | }, 328 | 'nthArg': function(nthArg) { 329 | return function(n) { 330 | var arity = n < 0 ? 1 : (toInteger(n) + 1); 331 | return curry(nthArg(n), arity); 332 | }; 333 | }, 334 | 'rearg': function(rearg) { 335 | return function(func, indexes) { 336 | var arity = indexes ? indexes.length : 0; 337 | return curry(rearg(func, indexes), arity); 338 | }; 339 | }, 340 | 'runInContext': function(runInContext) { 341 | return function(context) { 342 | return baseConvert(util, runInContext(context), options); 343 | }; 344 | } 345 | }; 346 | 347 | /*--------------------------------------------------------------------------*/ 348 | 349 | /** 350 | * Casts `func` to a function with an arity capped iteratee if needed. 351 | * 352 | * @private 353 | * @param {string} name The name of the function to inspect. 354 | * @param {Function} func The function to inspect. 355 | * @returns {Function} Returns the cast function. 356 | */ 357 | function castCap(name, func) { 358 | if (config.cap) { 359 | var indexes = mapping.iterateeRearg[name]; 360 | if (indexes) { 361 | return iterateeRearg(func, indexes); 362 | } 363 | var n = !isLib && mapping.iterateeAry[name]; 364 | if (n) { 365 | return iterateeAry(func, n); 366 | } 367 | } 368 | return func; 369 | } 370 | 371 | /** 372 | * Casts `func` to a curried function if needed. 373 | * 374 | * @private 375 | * @param {string} name The name of the function to inspect. 376 | * @param {Function} func The function to inspect. 377 | * @param {number} n The arity of `func`. 378 | * @returns {Function} Returns the cast function. 379 | */ 380 | function castCurry(name, func, n) { 381 | return (forceCurry || (config.curry && n > 1)) 382 | ? curry(func, n) 383 | : func; 384 | } 385 | 386 | /** 387 | * Casts `func` to a fixed arity function if needed. 388 | * 389 | * @private 390 | * @param {string} name The name of the function to inspect. 391 | * @param {Function} func The function to inspect. 392 | * @param {number} n The arity cap. 393 | * @returns {Function} Returns the cast function. 394 | */ 395 | function castFixed(name, func, n) { 396 | if (config.fixed && (forceFixed || !mapping.skipFixed[name])) { 397 | var data = mapping.methodSpread[name], 398 | start = data && data.start; 399 | 400 | return start === undefined ? ary(func, n) : flatSpread(func, start); 401 | } 402 | return func; 403 | } 404 | 405 | /** 406 | * Casts `func` to an rearged function if needed. 407 | * 408 | * @private 409 | * @param {string} name The name of the function to inspect. 410 | * @param {Function} func The function to inspect. 411 | * @param {number} n The arity of `func`. 412 | * @returns {Function} Returns the cast function. 413 | */ 414 | function castRearg(name, func, n) { 415 | return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name])) 416 | ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n]) 417 | : func; 418 | } 419 | 420 | /** 421 | * Creates a clone of `object` by `path`. 422 | * 423 | * @private 424 | * @param {Object} object The object to clone. 425 | * @param {Array|string} path The path to clone by. 426 | * @returns {Object} Returns the cloned object. 427 | */ 428 | function cloneByPath(object, path) { 429 | path = toPath(path); 430 | 431 | var index = -1, 432 | length = path.length, 433 | lastIndex = length - 1, 434 | result = clone(Object(object)), 435 | nested = result; 436 | 437 | while (nested != null && ++index < length) { 438 | var key = path[index], 439 | value = nested[key]; 440 | 441 | if (value != null && 442 | !(isFunction(value) || isError(value) || isWeakMap(value))) { 443 | nested[key] = clone(index == lastIndex ? value : Object(value)); 444 | } 445 | nested = nested[key]; 446 | } 447 | return result; 448 | } 449 | 450 | /** 451 | * Converts `lodash` to an immutable auto-curried iteratee-first data-last 452 | * version with conversion `options` applied. 453 | * 454 | * @param {Object} [options] The options object. See `baseConvert` for more details. 455 | * @returns {Function} Returns the converted `lodash`. 456 | */ 457 | function convertLib(options) { 458 | return _.runInContext.convert(options)(undefined); 459 | } 460 | 461 | /** 462 | * Create a converter function for `func` of `name`. 463 | * 464 | * @param {string} name The name of the function to convert. 465 | * @param {Function} func The function to convert. 466 | * @returns {Function} Returns the new converter function. 467 | */ 468 | function createConverter(name, func) { 469 | var realName = mapping.aliasToReal[name] || name, 470 | methodName = mapping.remap[realName] || realName, 471 | oldOptions = options; 472 | 473 | return function(options) { 474 | var newUtil = isLib ? pristine : helpers, 475 | newFunc = isLib ? pristine[methodName] : func, 476 | newOptions = assign(assign({}, oldOptions), options); 477 | 478 | return baseConvert(newUtil, realName, newFunc, newOptions); 479 | }; 480 | } 481 | 482 | /** 483 | * Creates a function that wraps `func` to invoke its iteratee, with up to `n` 484 | * arguments, ignoring any additional arguments. 485 | * 486 | * @private 487 | * @param {Function} func The function to cap iteratee arguments for. 488 | * @param {number} n The arity cap. 489 | * @returns {Function} Returns the new function. 490 | */ 491 | function iterateeAry(func, n) { 492 | return overArg(func, function(func) { 493 | return typeof func == 'function' ? baseAry(func, n) : func; 494 | }); 495 | } 496 | 497 | /** 498 | * Creates a function that wraps `func` to invoke its iteratee with arguments 499 | * arranged according to the specified `indexes` where the argument value at 500 | * the first index is provided as the first argument, the argument value at 501 | * the second index is provided as the second argument, and so on. 502 | * 503 | * @private 504 | * @param {Function} func The function to rearrange iteratee arguments for. 505 | * @param {number[]} indexes The arranged argument indexes. 506 | * @returns {Function} Returns the new function. 507 | */ 508 | function iterateeRearg(func, indexes) { 509 | return overArg(func, function(func) { 510 | var n = indexes.length; 511 | return baseArity(rearg(baseAry(func, n), indexes), n); 512 | }); 513 | } 514 | 515 | /** 516 | * Creates a function that invokes `func` with its first argument transformed. 517 | * 518 | * @private 519 | * @param {Function} func The function to wrap. 520 | * @param {Function} transform The argument transform. 521 | * @returns {Function} Returns the new function. 522 | */ 523 | function overArg(func, transform) { 524 | return function() { 525 | var length = arguments.length; 526 | if (!length) { 527 | return func(); 528 | } 529 | var args = Array(length); 530 | while (length--) { 531 | args[length] = arguments[length]; 532 | } 533 | var index = config.rearg ? 0 : (length - 1); 534 | args[index] = transform(args[index]); 535 | return func.apply(undefined, args); 536 | }; 537 | } 538 | 539 | /** 540 | * Creates a function that wraps `func` and applys the conversions 541 | * rules by `name`. 542 | * 543 | * @private 544 | * @param {string} name The name of the function to wrap. 545 | * @param {Function} func The function to wrap. 546 | * @returns {Function} Returns the converted function. 547 | */ 548 | function wrap(name, func, placeholder) { 549 | var result, 550 | realName = mapping.aliasToReal[name] || name, 551 | wrapped = func, 552 | wrapper = wrappers[realName]; 553 | 554 | if (wrapper) { 555 | wrapped = wrapper(func); 556 | } 557 | else if (config.immutable) { 558 | if (mapping.mutate.array[realName]) { 559 | wrapped = wrapImmutable(func, cloneArray); 560 | } 561 | else if (mapping.mutate.object[realName]) { 562 | wrapped = wrapImmutable(func, createCloner(func)); 563 | } 564 | else if (mapping.mutate.set[realName]) { 565 | wrapped = wrapImmutable(func, cloneByPath); 566 | } 567 | } 568 | each(aryMethodKeys, function(aryKey) { 569 | each(mapping.aryMethod[aryKey], function(otherName) { 570 | if (realName == otherName) { 571 | var data = mapping.methodSpread[realName], 572 | afterRearg = data && data.afterRearg; 573 | 574 | result = afterRearg 575 | ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey) 576 | : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey); 577 | 578 | result = castCap(realName, result); 579 | result = castCurry(realName, result, aryKey); 580 | return false; 581 | } 582 | }); 583 | return !result; 584 | }); 585 | 586 | result || (result = wrapped); 587 | if (result == func) { 588 | result = forceCurry ? curry(result, 1) : function() { 589 | return func.apply(this, arguments); 590 | }; 591 | } 592 | result.convert = createConverter(realName, func); 593 | result.placeholder = func.placeholder = placeholder; 594 | 595 | return result; 596 | } 597 | 598 | /*--------------------------------------------------------------------------*/ 599 | 600 | if (!isObj) { 601 | return wrap(name, func, defaultHolder); 602 | } 603 | var _ = func; 604 | 605 | // Convert methods by ary cap. 606 | var pairs = []; 607 | each(aryMethodKeys, function(aryKey) { 608 | each(mapping.aryMethod[aryKey], function(key) { 609 | var func = _[mapping.remap[key] || key]; 610 | if (func) { 611 | pairs.push([key, wrap(key, func, _)]); 612 | } 613 | }); 614 | }); 615 | 616 | // Convert remaining methods. 617 | each(keys(_), function(key) { 618 | var func = _[key]; 619 | if (typeof func == 'function') { 620 | var length = pairs.length; 621 | while (length--) { 622 | if (pairs[length][0] == key) { 623 | return; 624 | } 625 | } 626 | func.convert = createConverter(key, func); 627 | pairs.push([key, func]); 628 | } 629 | }); 630 | 631 | // Assign to `_` leaving `_.prototype` unchanged to allow chaining. 632 | each(pairs, function(pair) { 633 | _[pair[0]] = pair[1]; 634 | }); 635 | 636 | _.convert = convertLib; 637 | _.placeholder = _; 638 | 639 | // Assign aliases. 640 | each(keys(_), function(key) { 641 | each(mapping.realToAlias[key] || [], function(alias) { 642 | _[alias] = _[key]; 643 | }); 644 | }); 645 | 646 | return _; 647 | } 648 | 649 | module.exports = baseConvert; 650 | 651 | 652 | /***/ }), 653 | /* 2 */ 654 | /***/ (function(module, exports) { 655 | 656 | /** Used to map aliases to their real names. */ 657 | exports.aliasToReal = { 658 | 659 | // Lodash aliases. 660 | 'each': 'forEach', 661 | 'eachRight': 'forEachRight', 662 | 'entries': 'toPairs', 663 | 'entriesIn': 'toPairsIn', 664 | 'extend': 'assignIn', 665 | 'extendAll': 'assignInAll', 666 | 'extendAllWith': 'assignInAllWith', 667 | 'extendWith': 'assignInWith', 668 | 'first': 'head', 669 | 670 | // Methods that are curried variants of others. 671 | 'conforms': 'conformsTo', 672 | 'matches': 'isMatch', 673 | 'property': 'get', 674 | 675 | // Ramda aliases. 676 | '__': 'placeholder', 677 | 'F': 'stubFalse', 678 | 'T': 'stubTrue', 679 | 'all': 'every', 680 | 'allPass': 'overEvery', 681 | 'always': 'constant', 682 | 'any': 'some', 683 | 'anyPass': 'overSome', 684 | 'apply': 'spread', 685 | 'assoc': 'set', 686 | 'assocPath': 'set', 687 | 'complement': 'negate', 688 | 'compose': 'flowRight', 689 | 'contains': 'includes', 690 | 'dissoc': 'unset', 691 | 'dissocPath': 'unset', 692 | 'dropLast': 'dropRight', 693 | 'dropLastWhile': 'dropRightWhile', 694 | 'equals': 'isEqual', 695 | 'identical': 'eq', 696 | 'indexBy': 'keyBy', 697 | 'init': 'initial', 698 | 'invertObj': 'invert', 699 | 'juxt': 'over', 700 | 'omitAll': 'omit', 701 | 'nAry': 'ary', 702 | 'path': 'get', 703 | 'pathEq': 'matchesProperty', 704 | 'pathOr': 'getOr', 705 | 'paths': 'at', 706 | 'pickAll': 'pick', 707 | 'pipe': 'flow', 708 | 'pluck': 'map', 709 | 'prop': 'get', 710 | 'propEq': 'matchesProperty', 711 | 'propOr': 'getOr', 712 | 'props': 'at', 713 | 'symmetricDifference': 'xor', 714 | 'symmetricDifferenceBy': 'xorBy', 715 | 'symmetricDifferenceWith': 'xorWith', 716 | 'takeLast': 'takeRight', 717 | 'takeLastWhile': 'takeRightWhile', 718 | 'unapply': 'rest', 719 | 'unnest': 'flatten', 720 | 'useWith': 'overArgs', 721 | 'where': 'conformsTo', 722 | 'whereEq': 'isMatch', 723 | 'zipObj': 'zipObject' 724 | }; 725 | 726 | /** Used to map ary to method names. */ 727 | exports.aryMethod = { 728 | '1': [ 729 | 'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', 730 | 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', 731 | 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', 732 | 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse', 733 | 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', 734 | 'uniqueId', 'words', 'zipAll' 735 | ], 736 | '2': [ 737 | 'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', 738 | 'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith', 739 | 'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN', 740 | 'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference', 741 | 'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', 742 | 'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex', 743 | 'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach', 744 | 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', 745 | 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', 746 | 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', 747 | 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', 748 | 'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit', 749 | 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', 750 | 'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll', 751 | 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', 752 | 'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', 753 | 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', 754 | 'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', 755 | 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', 756 | 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', 757 | 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', 758 | 'zipObjectDeep' 759 | ], 760 | '3': [ 761 | 'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', 762 | 'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr', 763 | 'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith', 764 | 'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth', 765 | 'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd', 766 | 'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight', 767 | 'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', 768 | 'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy', 769 | 'xorWith', 'zipWith' 770 | ], 771 | '4': [ 772 | 'fill', 'setWith', 'updateWith' 773 | ] 774 | }; 775 | 776 | /** Used to map ary to rearg configs. */ 777 | exports.aryRearg = { 778 | '2': [1, 0], 779 | '3': [2, 0, 1], 780 | '4': [3, 2, 0, 1] 781 | }; 782 | 783 | /** Used to map method names to their iteratee ary. */ 784 | exports.iterateeAry = { 785 | 'dropRightWhile': 1, 786 | 'dropWhile': 1, 787 | 'every': 1, 788 | 'filter': 1, 789 | 'find': 1, 790 | 'findFrom': 1, 791 | 'findIndex': 1, 792 | 'findIndexFrom': 1, 793 | 'findKey': 1, 794 | 'findLast': 1, 795 | 'findLastFrom': 1, 796 | 'findLastIndex': 1, 797 | 'findLastIndexFrom': 1, 798 | 'findLastKey': 1, 799 | 'flatMap': 1, 800 | 'flatMapDeep': 1, 801 | 'flatMapDepth': 1, 802 | 'forEach': 1, 803 | 'forEachRight': 1, 804 | 'forIn': 1, 805 | 'forInRight': 1, 806 | 'forOwn': 1, 807 | 'forOwnRight': 1, 808 | 'map': 1, 809 | 'mapKeys': 1, 810 | 'mapValues': 1, 811 | 'partition': 1, 812 | 'reduce': 2, 813 | 'reduceRight': 2, 814 | 'reject': 1, 815 | 'remove': 1, 816 | 'some': 1, 817 | 'takeRightWhile': 1, 818 | 'takeWhile': 1, 819 | 'times': 1, 820 | 'transform': 2 821 | }; 822 | 823 | /** Used to map method names to iteratee rearg configs. */ 824 | exports.iterateeRearg = { 825 | 'mapKeys': [1], 826 | 'reduceRight': [1, 0] 827 | }; 828 | 829 | /** Used to map method names to rearg configs. */ 830 | exports.methodRearg = { 831 | 'assignInAllWith': [1, 0], 832 | 'assignInWith': [1, 2, 0], 833 | 'assignAllWith': [1, 0], 834 | 'assignWith': [1, 2, 0], 835 | 'differenceBy': [1, 2, 0], 836 | 'differenceWith': [1, 2, 0], 837 | 'getOr': [2, 1, 0], 838 | 'intersectionBy': [1, 2, 0], 839 | 'intersectionWith': [1, 2, 0], 840 | 'isEqualWith': [1, 2, 0], 841 | 'isMatchWith': [2, 1, 0], 842 | 'mergeAllWith': [1, 0], 843 | 'mergeWith': [1, 2, 0], 844 | 'padChars': [2, 1, 0], 845 | 'padCharsEnd': [2, 1, 0], 846 | 'padCharsStart': [2, 1, 0], 847 | 'pullAllBy': [2, 1, 0], 848 | 'pullAllWith': [2, 1, 0], 849 | 'rangeStep': [1, 2, 0], 850 | 'rangeStepRight': [1, 2, 0], 851 | 'setWith': [3, 1, 2, 0], 852 | 'sortedIndexBy': [2, 1, 0], 853 | 'sortedLastIndexBy': [2, 1, 0], 854 | 'unionBy': [1, 2, 0], 855 | 'unionWith': [1, 2, 0], 856 | 'updateWith': [3, 1, 2, 0], 857 | 'xorBy': [1, 2, 0], 858 | 'xorWith': [1, 2, 0], 859 | 'zipWith': [1, 2, 0] 860 | }; 861 | 862 | /** Used to map method names to spread configs. */ 863 | exports.methodSpread = { 864 | 'assignAll': { 'start': 0 }, 865 | 'assignAllWith': { 'start': 0 }, 866 | 'assignInAll': { 'start': 0 }, 867 | 'assignInAllWith': { 'start': 0 }, 868 | 'defaultsAll': { 'start': 0 }, 869 | 'defaultsDeepAll': { 'start': 0 }, 870 | 'invokeArgs': { 'start': 2 }, 871 | 'invokeArgsMap': { 'start': 2 }, 872 | 'mergeAll': { 'start': 0 }, 873 | 'mergeAllWith': { 'start': 0 }, 874 | 'partial': { 'start': 1 }, 875 | 'partialRight': { 'start': 1 }, 876 | 'without': { 'start': 1 }, 877 | 'zipAll': { 'start': 0 } 878 | }; 879 | 880 | /** Used to identify methods which mutate arrays or objects. */ 881 | exports.mutate = { 882 | 'array': { 883 | 'fill': true, 884 | 'pull': true, 885 | 'pullAll': true, 886 | 'pullAllBy': true, 887 | 'pullAllWith': true, 888 | 'pullAt': true, 889 | 'remove': true, 890 | 'reverse': true 891 | }, 892 | 'object': { 893 | 'assign': true, 894 | 'assignAll': true, 895 | 'assignAllWith': true, 896 | 'assignIn': true, 897 | 'assignInAll': true, 898 | 'assignInAllWith': true, 899 | 'assignInWith': true, 900 | 'assignWith': true, 901 | 'defaults': true, 902 | 'defaultsAll': true, 903 | 'defaultsDeep': true, 904 | 'defaultsDeepAll': true, 905 | 'merge': true, 906 | 'mergeAll': true, 907 | 'mergeAllWith': true, 908 | 'mergeWith': true, 909 | }, 910 | 'set': { 911 | 'set': true, 912 | 'setWith': true, 913 | 'unset': true, 914 | 'update': true, 915 | 'updateWith': true 916 | } 917 | }; 918 | 919 | /** Used to map real names to their aliases. */ 920 | exports.realToAlias = (function() { 921 | var hasOwnProperty = Object.prototype.hasOwnProperty, 922 | object = exports.aliasToReal, 923 | result = {}; 924 | 925 | for (var key in object) { 926 | var value = object[key]; 927 | if (hasOwnProperty.call(result, value)) { 928 | result[value].push(key); 929 | } else { 930 | result[value] = [key]; 931 | } 932 | } 933 | return result; 934 | }()); 935 | 936 | /** Used to map method names to other names. */ 937 | exports.remap = { 938 | 'assignAll': 'assign', 939 | 'assignAllWith': 'assignWith', 940 | 'assignInAll': 'assignIn', 941 | 'assignInAllWith': 'assignInWith', 942 | 'curryN': 'curry', 943 | 'curryRightN': 'curryRight', 944 | 'defaultsAll': 'defaults', 945 | 'defaultsDeepAll': 'defaultsDeep', 946 | 'findFrom': 'find', 947 | 'findIndexFrom': 'findIndex', 948 | 'findLastFrom': 'findLast', 949 | 'findLastIndexFrom': 'findLastIndex', 950 | 'getOr': 'get', 951 | 'includesFrom': 'includes', 952 | 'indexOfFrom': 'indexOf', 953 | 'invokeArgs': 'invoke', 954 | 'invokeArgsMap': 'invokeMap', 955 | 'lastIndexOfFrom': 'lastIndexOf', 956 | 'mergeAll': 'merge', 957 | 'mergeAllWith': 'mergeWith', 958 | 'padChars': 'pad', 959 | 'padCharsEnd': 'padEnd', 960 | 'padCharsStart': 'padStart', 961 | 'propertyOf': 'get', 962 | 'rangeStep': 'range', 963 | 'rangeStepRight': 'rangeRight', 964 | 'restFrom': 'rest', 965 | 'spreadFrom': 'spread', 966 | 'trimChars': 'trim', 967 | 'trimCharsEnd': 'trimEnd', 968 | 'trimCharsStart': 'trimStart', 969 | 'zipAll': 'zip' 970 | }; 971 | 972 | /** Used to track methods that skip fixing their arity. */ 973 | exports.skipFixed = { 974 | 'castArray': true, 975 | 'flow': true, 976 | 'flowRight': true, 977 | 'iteratee': true, 978 | 'mixin': true, 979 | 'rearg': true, 980 | 'runInContext': true 981 | }; 982 | 983 | /** Used to track methods that skip rearranging arguments. */ 984 | exports.skipRearg = { 985 | 'add': true, 986 | 'assign': true, 987 | 'assignIn': true, 988 | 'bind': true, 989 | 'bindKey': true, 990 | 'concat': true, 991 | 'difference': true, 992 | 'divide': true, 993 | 'eq': true, 994 | 'gt': true, 995 | 'gte': true, 996 | 'isEqual': true, 997 | 'lt': true, 998 | 'lte': true, 999 | 'matchesProperty': true, 1000 | 'merge': true, 1001 | 'multiply': true, 1002 | 'overArgs': true, 1003 | 'partial': true, 1004 | 'partialRight': true, 1005 | 'propertyOf': true, 1006 | 'random': true, 1007 | 'range': true, 1008 | 'rangeRight': true, 1009 | 'subtract': true, 1010 | 'zip': true, 1011 | 'zipObject': true, 1012 | 'zipObjectDeep': true 1013 | }; 1014 | 1015 | 1016 | /***/ }), 1017 | /* 3 */ 1018 | /***/ (function(module, exports) { 1019 | 1020 | /** 1021 | * The default argument placeholder value for methods. 1022 | * 1023 | * @type {Object} 1024 | */ 1025 | module.exports = {}; 1026 | 1027 | 1028 | /***/ }) 1029 | /******/ ]) 1030 | }); 1031 | ; 1032 | -------------------------------------------------------------------------------- /fixtures/ts-sample.ts: -------------------------------------------------------------------------------- 1 | // Loads a lot of libraries and demonstrates various TypeScript features 2 | import 'autocannon'; 3 | import 'dotenv'; 4 | import 'fastify'; 5 | import 'lodash'; 6 | import 'moment'; 7 | import 'pino'; 8 | import 'piscina'; 9 | import 'prettier'; 10 | import 'tinybench'; 11 | import 'typescript'; 12 | import 'underscore'; 13 | import 'winston'; 14 | 15 | // Decorators 16 | function Logger(target: any, propertyKey: string) { 17 | console.log(`Property ${propertyKey} has been accessed at ${target}`); 18 | } 19 | 20 | // Enums 21 | enum Color { 22 | Red, 23 | Green, 24 | Blue, 25 | Yellow, 26 | Purple, 27 | Cyan, 28 | Magenta, 29 | White, 30 | Black, 31 | Orange, 32 | Pink, 33 | Brown, 34 | Grey, 35 | Violet, 36 | Indigo 37 | } 38 | 39 | // Interfaces 40 | interface Person { 41 | name: string; 42 | age: number; 43 | greet(): void; 44 | } 45 | 46 | interface Employee extends Person { 47 | employeeId: number; 48 | department: string; 49 | } 50 | 51 | // Generic Interface 52 | interface Repository { 53 | getById(id: number): T; 54 | save(entity: T): void; 55 | delete(id: number): void; 56 | getAll(): T[]; 57 | } 58 | 59 | Logger({ name: 'Alice', age: 30 }, 'name'); 60 | 61 | // Classes with generics and decorators 62 | class User implements Person { 63 | name: string; 64 | age: number; 65 | private static instance: User; 66 | 67 | constructor(name: string, age: number) { 68 | this.name = name; 69 | this.age = age; 70 | } 71 | 72 | static getInstance(name: string, age: number): User { 73 | if (!User.instance) { 74 | User.instance = new User(name, age); 75 | } 76 | return User.instance; 77 | } 78 | 79 | greet() { 80 | console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); 81 | } 82 | 83 | changeName(newName: string): void { 84 | this.name = newName; 85 | } 86 | } 87 | 88 | class Manager extends User implements Employee { 89 | employeeId: number; 90 | department: string; 91 | 92 | constructor(name: string, age: number, employeeId: number, department: string) { 93 | super(name, age); 94 | this.employeeId = employeeId; 95 | this.department = department; 96 | } 97 | 98 | greet() { 99 | super.greet(); 100 | console.log( 101 | `I am a manager of the ${this.department} department with ID: ${this.employeeId}` 102 | ); 103 | } 104 | } 105 | 106 | // Abstract class 107 | abstract class Animal { 108 | constructor(public name: string) {} 109 | 110 | abstract makeSound(): void; 111 | 112 | move(): void { 113 | console.log(`${this.name} is moving.`); 114 | } 115 | } 116 | 117 | // Inheritance 118 | class Dog extends Animal { 119 | makeSound() { 120 | console.log('Woof! Woof!'); 121 | } 122 | } 123 | 124 | class Cat extends Animal { 125 | makeSound() { 126 | console.log('Meow! Meow!'); 127 | } 128 | } 129 | 130 | class Bird extends Animal { 131 | makeSound() { 132 | console.log('Chirp! Chirp!'); 133 | } 134 | } 135 | 136 | // Mixins 137 | type Constructor = new (...args: any[]) => T; 138 | 139 | function Timestamped(Base: TBase) { 140 | return class extends Base { 141 | timestamp = new Date(); 142 | }; 143 | } 144 | 145 | function Identifiable(Base: TBase) { 146 | return class extends Base { 147 | id = Math.floor(Math.random() * 10000); 148 | }; 149 | } 150 | 151 | class BasicLogger { 152 | log(message: string) { 153 | console.log(message); 154 | } 155 | } 156 | 157 | const TimestampedLogger = Timestamped(BasicLogger); 158 | const IdentifiedLogger = Identifiable(TimestampedLogger); 159 | 160 | const logger = new IdentifiedLogger(); 161 | logger.log('This is a log message with a timestamp and ID.'); 162 | console.log(logger.timestamp); 163 | console.log(logger.id); 164 | 165 | // Namespaces 166 | namespace MathOperations { 167 | export function add(x: number, y: number): number { 168 | return x + y; 169 | } 170 | 171 | export function subtract(x: number, y: number): number { 172 | return x - y; 173 | } 174 | 175 | export namespace Advanced { 176 | export function multiply(x: number, y: number): number { 177 | return x * y; 178 | } 179 | 180 | export function divide(x: number, y: number): number { 181 | if (y === 0) { 182 | throw new Error('Division by zero'); 183 | } 184 | return x / y; 185 | } 186 | 187 | export function power(base: number, exponent: number): number { 188 | return Math.pow(base, exponent); 189 | } 190 | } 191 | } 192 | 193 | // Generics and Utility Types 194 | type Nullable = T | null; 195 | 196 | class IResponse { 197 | constructor( 198 | public data: Nullable, 199 | public error: Nullable = null 200 | ) {} 201 | } 202 | 203 | // Type Aliases and Union Types 204 | type ID = string | number; 205 | 206 | function printID(id: ID): void { 207 | if (typeof id === 'string') { 208 | console.log(`ID is a string: ${id}`); 209 | } else { 210 | console.log(`ID is a number: ${id}`); 211 | } 212 | } 213 | 214 | // Tuples 215 | let point: [number, number] = [10, 20]; 216 | let complexPoint: [number, number, number] = [10, 20, 30]; 217 | 218 | // Assertions 219 | let someValue: any = 'This is a string'; 220 | let strLength: number = (someValue as string).length; 221 | 222 | // Function Overloads 223 | function add(a: number, b: number): number; 224 | function add(a: string, b: string): string; 225 | function add(a: any, b: any): any { 226 | return a + b; 227 | } 228 | 229 | // More Classes, Interfaces, and Functions 230 | interface Car { 231 | make: string; 232 | model: string; 233 | year: number; 234 | drive(): void; 235 | } 236 | 237 | class SportsCar implements Car { 238 | constructor( 239 | public make: string, 240 | public model: string, 241 | public year: number 242 | ) {} 243 | 244 | drive() { 245 | console.log(`Driving a ${this.year} ${this.make} ${this.model}`); 246 | } 247 | } 248 | 249 | interface Bicycle { 250 | brand: string; 251 | gearCount: number; 252 | ride(): void; 253 | } 254 | 255 | class MountainBike implements Bicycle { 256 | constructor( 257 | public brand: string, 258 | public gearCount: number 259 | ) {} 260 | 261 | ride() { 262 | console.log(`Riding a ${this.brand} mountain bike with ${this.gearCount} gears`); 263 | } 264 | } 265 | 266 | class HybridBike extends MountainBike { 267 | constructor( 268 | brand: string, 269 | gearCount: number, 270 | public hasElectricAssist: boolean 271 | ) { 272 | super(brand, gearCount); 273 | } 274 | 275 | ride() { 276 | super.ride(); 277 | if (this.hasElectricAssist) { 278 | console.log('This bike has electric assist.'); 279 | } 280 | } 281 | } 282 | 283 | // Using the code 284 | const user1 = User.getInstance('Alice', 30); 285 | user1.greet(); 286 | user1.changeName('Alicia'); 287 | user1.greet(); 288 | 289 | const manager = new Manager('Bob', 45, 101, 'Sales'); 290 | manager.greet(); 291 | 292 | const repo: Repository = { 293 | getById(id: number): User { 294 | return User.getInstance('Sample User', 25); 295 | }, 296 | save(user: User): void { 297 | console.log(`User saved: ${user.name}`); 298 | }, 299 | delete(id: number): void { 300 | console.log(`User with ID ${id} deleted`); 301 | }, 302 | getAll(): User[] { 303 | return [User.getInstance('Sample User', 25)]; 304 | } 305 | }; 306 | 307 | const dog = new Dog('Buddy'); 308 | dog.makeSound(); 309 | dog.move(); 310 | 311 | const cat = new Cat('Whiskers'); 312 | cat.makeSound(); 313 | cat.move(); 314 | 315 | const bird = new Bird('Tweety'); 316 | bird.makeSound(); 317 | bird.move(); 318 | 319 | console.log(Color.Green); 320 | 321 | console.log(MathOperations.add(5, 10)); 322 | console.log(MathOperations.Advanced.multiply(3, 7)); 323 | console.log(MathOperations.Advanced.power(2, 3)); 324 | 325 | const response = new IResponse(user1); 326 | console.log(response.data?.name); 327 | 328 | printID('abc123'); 329 | printID(98765); 330 | 331 | console.log(point); 332 | console.log(complexPoint); 333 | console.log(`Length of someValue: ${strLength}`); 334 | 335 | console.log(add(10, 20)); 336 | console.log(add('Hello, ', 'world!')); 337 | 338 | const sportsCar = new SportsCar('Ferrari', '488', 2021); 339 | sportsCar.drive(); 340 | 341 | const mountainBike = new MountainBike('Trek', 18); 342 | mountainBike.ride(); 343 | 344 | const hybridBike = new HybridBike('Specialized', 21, true); 345 | hybridBike.ride(); 346 | 347 | // More namespaces and functions 348 | namespace Geometry { 349 | export interface Shape { 350 | area(): number; 351 | perimeter(): number; 352 | } 353 | 354 | export class Rectangle implements Shape { 355 | constructor( 356 | public width: number, 357 | public height: number 358 | ) {} 359 | 360 | area(): number { 361 | return this.width * this.height; 362 | } 363 | 364 | perimeter(): number { 365 | return 2 * (this.width + this.height); 366 | } 367 | } 368 | 369 | export class Circle implements Shape { 370 | constructor(public radius: number) {} 371 | 372 | area(): number { 373 | return Math.PI * this.radius * this.radius; 374 | } 375 | 376 | perimeter(): number { 377 | return 2 * Math.PI * this.radius; 378 | } 379 | } 380 | 381 | export class Triangle implements Shape { 382 | constructor( 383 | public base: number, 384 | public height: number 385 | ) {} 386 | 387 | area(): number { 388 | return 0.5 * this.base * this.height; 389 | } 390 | 391 | perimeter(): number { 392 | // Assuming an equilateral triangle for simplicity 393 | return 3 * this.base; 394 | } 395 | } 396 | } 397 | 398 | const rectangle = new Geometry.Rectangle(10, 20); 399 | console.log(`Rectangle Area: ${rectangle.area()}`); 400 | console.log(`Rectangle Perimeter: ${rectangle.perimeter()}`); 401 | 402 | const circle = new Geometry.Circle(10); 403 | console.log(`Circle Area: ${circle.area()}`); 404 | console.log(`Circle Perimeter: ${circle.perimeter()}`); 405 | 406 | const triangle = new Geometry.Triangle(10, 20); 407 | console.log(`Triangle Area: ${triangle.area()}`); 408 | console.log(`Triangle Perimeter: ${triangle.perimeter()}`); 409 | 410 | // More mixins and classes 411 | function Serializable(Base: TBase) { 412 | return class extends Base { 413 | serialize() { 414 | return JSON.stringify(this); 415 | } 416 | }; 417 | } 418 | 419 | class DataClass { 420 | constructor(public data: string) {} 421 | } 422 | 423 | const SerializableDataClass = Serializable(DataClass); 424 | new SerializableDataClass('Some data'); 425 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node --allow-natives-syntax 2 | 3 | const fs = require('node:fs/promises'); 4 | const path = require('node:path'); 5 | const Piscina = require('piscina'); 6 | const os = require('node:os'); 7 | 8 | const piscina = new Piscina({ 9 | filename: path.resolve(__dirname, 'worker.js'), 10 | resourceLimits: { 11 | // 16GiB for each Worker (1 per run) 12 | // This was required due to prettier benchmark 13 | maxOldGenerationSizeMb: 16384 14 | }, 15 | maxQueue: 1 16 | }); 17 | 18 | let output; 19 | // Considering this script won't be called as a 20 | // child_process, stdout.isTTY should be reliable enough. 21 | if (process.env.TTY || process.stdout.isTTY) { 22 | output = require('./console-output'); 23 | } else { 24 | const results = []; 25 | 26 | output = { 27 | info: () => {}, 28 | start: () => {}, 29 | end: () => console.log(JSON.stringify(results, null, 2)), 30 | step: (result) => results.push(result) 31 | }; 32 | } 33 | 34 | async function main() { 35 | const files = await fs.readdir(path.join(__dirname, './src')); 36 | output.info(`cpu: ${os.cpus()[0].model} (${os.cpus().length} cores)`); 37 | output.info(`node: ${process.version} (${process.execPath})`); 38 | output.info(`os: ${os.type()} ${os.release()} ${os.arch()}`); 39 | 40 | output.start(); 41 | 42 | for (const file of files) { 43 | if (!file.match(/.*-benchmark\.js$/)) { 44 | continue; 45 | } 46 | 47 | const benchFile = path.join(__dirname, './src/', file); 48 | const result = await piscina.run(benchFile); 49 | output.step(result); 50 | } 51 | 52 | output.end(); 53 | } 54 | 55 | main(); 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-package-benchmark", 3 | "description": "This package allows you to benchmark different runtimes using popular packages operations.", 4 | "version": "1.1.0-beta.3", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/NodeSource/nodejs-package-benchmark.git" 12 | }, 13 | "keywords": [ 14 | "benchmark", 15 | "nodejs", 16 | "core" 17 | ], 18 | "author": "RafaelGSS ", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/NodeSource/nodejs-package-benchmark/issues" 22 | }, 23 | "homepage": "https://github.com/NodeSource/nodejs-package-benchmark#readme", 24 | "bin": { 25 | "bench-it": "./bench-it.js" 26 | }, 27 | "dependencies": { 28 | "@babel/standalone": "7.24.0", 29 | "@types/autocannon": "7.12.5", 30 | "@types/lodash": "4.17.3", 31 | "@types/underscore": "1.11.15", 32 | "autocannon": "7.15.0", 33 | "bench-node": "0.1.0", 34 | "dotenv": "16.4.5", 35 | "fastify": "4.26.1", 36 | "lodash": "4.17.21", 37 | "moment": "2.30.1", 38 | "pino": "8.19.0", 39 | "piscina": "4.4.0", 40 | "prettier": "3.2.5", 41 | "tinybench": "2.6.0", 42 | "typescript": "5.4.5", 43 | "underscore": "1.13.6", 44 | "winston": "3.12.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@babel/standalone': 12 | specifier: 7.24.0 13 | version: 7.24.0 14 | '@types/autocannon': 15 | specifier: 7.12.5 16 | version: 7.12.5 17 | '@types/lodash': 18 | specifier: 4.17.3 19 | version: 4.17.3 20 | '@types/underscore': 21 | specifier: 1.11.15 22 | version: 1.11.15 23 | autocannon: 24 | specifier: 7.15.0 25 | version: 7.15.0 26 | bench-node: 27 | specifier: 0.1.0 28 | version: 0.1.0 29 | dotenv: 30 | specifier: 16.4.5 31 | version: 16.4.5 32 | fastify: 33 | specifier: 4.26.1 34 | version: 4.26.1 35 | lodash: 36 | specifier: 4.17.21 37 | version: 4.17.21 38 | moment: 39 | specifier: 2.30.1 40 | version: 2.30.1 41 | pino: 42 | specifier: 8.19.0 43 | version: 8.19.0 44 | piscina: 45 | specifier: 4.4.0 46 | version: 4.4.0 47 | prettier: 48 | specifier: 3.2.5 49 | version: 3.2.5 50 | tinybench: 51 | specifier: 2.6.0 52 | version: 2.6.0 53 | typescript: 54 | specifier: 5.4.5 55 | version: 5.4.5 56 | underscore: 57 | specifier: 1.13.6 58 | version: 1.13.6 59 | winston: 60 | specifier: 3.12.0 61 | version: 3.12.0 62 | 63 | packages: 64 | 65 | '@assemblyscript/loader@0.19.23': 66 | resolution: {integrity: sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==} 67 | 68 | '@babel/standalone@7.24.0': 69 | resolution: {integrity: sha512-yIZ/X3EAASgX/MW1Bn8iZKxCwixgYJAUaIScoZ9C6Gapw5l3eKIbtVSgO/IGldQed9QXm22yurKVWyWj5/j+SQ==} 70 | engines: {node: '>=6.9.0'} 71 | 72 | '@colors/colors@1.5.0': 73 | resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} 74 | engines: {node: '>=0.1.90'} 75 | 76 | '@colors/colors@1.6.0': 77 | resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} 78 | engines: {node: '>=0.1.90'} 79 | 80 | '@dabh/diagnostics@2.0.3': 81 | resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} 82 | 83 | '@fastify/ajv-compiler@3.5.0': 84 | resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} 85 | 86 | '@fastify/error@3.4.1': 87 | resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} 88 | 89 | '@fastify/fast-json-stringify-compiler@4.3.0': 90 | resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} 91 | 92 | '@fastify/merge-json-schemas@0.1.1': 93 | resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} 94 | 95 | '@types/autocannon@7.12.5': 96 | resolution: {integrity: sha512-IGxnlq0ip0DTDOpShCDOjsBW+lclASdli1Jep+YSEOeUwylwyMai3WCVLi0mnXjHPD1cIziz3eiVyX6i7toB7Q==} 97 | 98 | '@types/lodash@4.17.3': 99 | resolution: {integrity: sha512-zmNrEJaBvNskZXQWaUQq6bktF4IDGVfDS78M+YEk5aCn9M/b94/mB/6WCyfH2/MjwBdc6QuOor95CIlKWYRL3A==} 100 | 101 | '@types/node@20.12.12': 102 | resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} 103 | 104 | '@types/triple-beam@1.3.5': 105 | resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} 106 | 107 | '@types/underscore@1.11.15': 108 | resolution: {integrity: sha512-HP38xE+GuWGlbSRq9WrZkousaQ7dragtZCruBVMi0oX1migFZavZ3OROKHSkNp/9ouq82zrWtZpg18jFnVN96g==} 109 | 110 | abort-controller@3.0.0: 111 | resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} 112 | engines: {node: '>=6.5'} 113 | 114 | abstract-logging@2.0.1: 115 | resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} 116 | 117 | ajv-formats@2.1.1: 118 | resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} 119 | peerDependencies: 120 | ajv: ^8.0.0 121 | peerDependenciesMeta: 122 | ajv: 123 | optional: true 124 | 125 | ajv@8.12.0: 126 | resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} 127 | 128 | ansi-regex@5.0.1: 129 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 130 | engines: {node: '>=8'} 131 | 132 | ansi-styles@4.3.0: 133 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 134 | engines: {node: '>=8'} 135 | 136 | archy@1.0.0: 137 | resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} 138 | 139 | async@3.2.5: 140 | resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} 141 | 142 | asynckit@0.4.0: 143 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 144 | 145 | atomic-sleep@1.0.0: 146 | resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} 147 | engines: {node: '>=8.0.0'} 148 | 149 | autocannon@7.15.0: 150 | resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==} 151 | hasBin: true 152 | 153 | avvio@8.3.0: 154 | resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} 155 | 156 | base64-js@1.5.1: 157 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 158 | 159 | bench-node@0.1.0: 160 | resolution: {integrity: sha512-bqsGRu63dp5ocHQhSdesfujRqhj4GbP75kHKE+0FMhYA1MmyxwrwAbj8lTrqlenlmQLT9ya8idjLYjPIzf7Mmg==} 161 | 162 | buffer@5.7.1: 163 | resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 164 | 165 | buffer@6.0.3: 166 | resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 167 | 168 | chalk@4.1.2: 169 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 170 | engines: {node: '>=10'} 171 | 172 | char-spinner@1.0.1: 173 | resolution: {integrity: sha512-acv43vqJ0+N0rD+Uw3pDHSxP30FHrywu2NO6/wBaHChJIizpDeBUd6NjqhNhy9LGaEAhZAXn46QzmlAvIWd16g==} 174 | 175 | cli-table3@0.6.3: 176 | resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} 177 | engines: {node: 10.* || >= 12.*} 178 | 179 | color-convert@1.9.3: 180 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 181 | 182 | color-convert@2.0.1: 183 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 184 | engines: {node: '>=7.0.0'} 185 | 186 | color-name@1.1.3: 187 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 188 | 189 | color-name@1.1.4: 190 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 191 | 192 | color-string@1.9.1: 193 | resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} 194 | 195 | color-support@1.1.3: 196 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} 197 | hasBin: true 198 | 199 | color@3.2.1: 200 | resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} 201 | 202 | colorspace@1.1.4: 203 | resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} 204 | 205 | combined-stream@1.0.8: 206 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 207 | engines: {node: '>= 0.8'} 208 | 209 | cookie@0.6.0: 210 | resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} 211 | engines: {node: '>= 0.6'} 212 | 213 | cross-argv@2.0.0: 214 | resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} 215 | 216 | debug@4.3.4: 217 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 218 | engines: {node: '>=6.0'} 219 | peerDependencies: 220 | supports-color: '*' 221 | peerDependenciesMeta: 222 | supports-color: 223 | optional: true 224 | 225 | delayed-stream@1.0.0: 226 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 227 | engines: {node: '>=0.4.0'} 228 | 229 | dotenv@16.4.5: 230 | resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} 231 | engines: {node: '>=12'} 232 | 233 | emoji-regex@8.0.0: 234 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 235 | 236 | enabled@2.0.0: 237 | resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} 238 | 239 | event-target-shim@5.0.1: 240 | resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} 241 | engines: {node: '>=6'} 242 | 243 | events@3.3.0: 244 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 245 | engines: {node: '>=0.8.x'} 246 | 247 | fast-content-type-parse@1.1.0: 248 | resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} 249 | 250 | fast-decode-uri-component@1.0.1: 251 | resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} 252 | 253 | fast-deep-equal@3.1.3: 254 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 255 | 256 | fast-json-stringify@5.12.0: 257 | resolution: {integrity: sha512-7Nnm9UPa7SfHRbHVA1kJQrGXCRzB7LMlAAqHXQFkEQqueJm1V8owm0FsE/2Do55/4CcdhwiLQERaKomOnKQkyA==} 258 | 259 | fast-querystring@1.1.2: 260 | resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} 261 | 262 | fast-redact@3.3.0: 263 | resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==} 264 | engines: {node: '>=6'} 265 | 266 | fast-uri@2.3.0: 267 | resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} 268 | 269 | fastify@4.26.1: 270 | resolution: {integrity: sha512-tznA/G55dsxzM5XChBfcvVSloG2ejeeotfPPJSFaWmHyCDVGMpvf3nRNbsCb/JTBF9RmQFBfuujWt3Nphjesng==} 271 | 272 | fastq@1.17.1: 273 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 274 | 275 | fecha@4.2.3: 276 | resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} 277 | 278 | find-my-way@8.2.2: 279 | resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} 280 | engines: {node: '>=14'} 281 | 282 | fn.name@1.1.0: 283 | resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} 284 | 285 | form-data@4.0.0: 286 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} 287 | engines: {node: '>= 6'} 288 | 289 | forwarded@0.2.0: 290 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 291 | engines: {node: '>= 0.6'} 292 | 293 | has-async-hooks@1.0.0: 294 | resolution: {integrity: sha512-YF0VPGjkxr7AyyQQNykX8zK4PvtEDsUJAPqwu06UFz1lb6EvI53sPh5H1kWxg8NXI5LsfRCZ8uX9NkYDZBb/mw==} 295 | 296 | has-flag@4.0.0: 297 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 298 | engines: {node: '>=8'} 299 | 300 | hdr-histogram-js@3.0.0: 301 | resolution: {integrity: sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==} 302 | engines: {node: '>=14'} 303 | 304 | hdr-histogram-percentiles-obj@3.0.0: 305 | resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==} 306 | 307 | http-parser-js@0.5.8: 308 | resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} 309 | 310 | hyperid@3.2.0: 311 | resolution: {integrity: sha512-PdTtDo+Rmza9nEhTunaDSUKwbC69TIzLEpZUwiB6f+0oqmY0UPfhyHCPt6K1NQ4WFv5yJBTG5vELztVWP+nEVQ==} 312 | 313 | ieee754@1.2.1: 314 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 315 | 316 | inherits@2.0.4: 317 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 318 | 319 | ipaddr.js@1.9.1: 320 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 321 | engines: {node: '>= 0.10'} 322 | 323 | is-arrayish@0.3.2: 324 | resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} 325 | 326 | is-fullwidth-code-point@3.0.0: 327 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 328 | engines: {node: '>=8'} 329 | 330 | is-stream@2.0.1: 331 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 332 | engines: {node: '>=8'} 333 | 334 | json-schema-ref-resolver@1.0.1: 335 | resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} 336 | 337 | json-schema-traverse@1.0.0: 338 | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 339 | 340 | kuler@2.0.0: 341 | resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} 342 | 343 | light-my-request@5.11.1: 344 | resolution: {integrity: sha512-KXAh2m6VRlkWCk2KfmHE7tLBXKh30JE0tXUJY4dNxje4oLmPKUqlUfImiEQZLphx+Z9KTQcVv4DjGnJxkVOIbA==} 345 | 346 | lodash.chunk@4.2.0: 347 | resolution: {integrity: sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==} 348 | 349 | lodash.clonedeep@4.5.0: 350 | resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} 351 | 352 | lodash.flatten@4.4.0: 353 | resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} 354 | 355 | lodash@4.17.21: 356 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 357 | 358 | logform@2.6.0: 359 | resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} 360 | engines: {node: '>= 12.0.0'} 361 | 362 | lru-cache@6.0.0: 363 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 364 | engines: {node: '>=10'} 365 | 366 | manage-path@2.0.0: 367 | resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==} 368 | 369 | mime-db@1.52.0: 370 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 371 | engines: {node: '>= 0.6'} 372 | 373 | mime-types@2.1.35: 374 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 375 | engines: {node: '>= 0.6'} 376 | 377 | minimist@1.2.8: 378 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 379 | 380 | moment@2.30.1: 381 | resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} 382 | 383 | ms@2.1.2: 384 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 385 | 386 | nice-napi@1.0.2: 387 | resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} 388 | os: ['!win32'] 389 | 390 | node-addon-api@3.2.1: 391 | resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} 392 | 393 | node-gyp-build@4.8.0: 394 | resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} 395 | hasBin: true 396 | 397 | on-exit-leak-free@2.1.2: 398 | resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} 399 | engines: {node: '>=14.0.0'} 400 | 401 | on-net-listen@1.1.2: 402 | resolution: {integrity: sha512-y1HRYy8s/RlcBvDUwKXSmkODMdx4KSuIvloCnQYJ2LdBBC1asY4HtfhXwe3UWknLakATZDnbzht2Ijw3M1EqFg==} 403 | engines: {node: '>=9.4.0 || ^8.9.4'} 404 | 405 | one-time@1.0.0: 406 | resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} 407 | 408 | pako@1.0.11: 409 | resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} 410 | 411 | pino-abstract-transport@1.1.0: 412 | resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} 413 | 414 | pino-std-serializers@6.2.2: 415 | resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} 416 | 417 | pino@8.19.0: 418 | resolution: {integrity: sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==} 419 | hasBin: true 420 | 421 | piscina@4.4.0: 422 | resolution: {integrity: sha512-+AQduEJefrOApE4bV7KRmp3N2JnnyErlVqq4P/jmko4FPz9Z877BCccl/iB3FdrWSUkvbGV9Kan/KllJgat3Vg==} 423 | 424 | prettier@3.2.5: 425 | resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} 426 | engines: {node: '>=14'} 427 | hasBin: true 428 | 429 | pretty-bytes@5.6.0: 430 | resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} 431 | engines: {node: '>=6'} 432 | 433 | process-warning@2.3.2: 434 | resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==} 435 | 436 | process-warning@3.0.0: 437 | resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} 438 | 439 | process@0.11.10: 440 | resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} 441 | engines: {node: '>= 0.6.0'} 442 | 443 | progress@2.0.3: 444 | resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} 445 | engines: {node: '>=0.4.0'} 446 | 447 | proxy-addr@2.0.7: 448 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 449 | engines: {node: '>= 0.10'} 450 | 451 | punycode@2.3.1: 452 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 453 | engines: {node: '>=6'} 454 | 455 | quick-format-unescaped@4.0.4: 456 | resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} 457 | 458 | readable-stream@3.6.2: 459 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 460 | engines: {node: '>= 6'} 461 | 462 | readable-stream@4.5.2: 463 | resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} 464 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 465 | 466 | real-require@0.2.0: 467 | resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} 468 | engines: {node: '>= 12.13.0'} 469 | 470 | reinterval@1.1.0: 471 | resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==} 472 | 473 | require-from-string@2.0.2: 474 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 475 | engines: {node: '>=0.10.0'} 476 | 477 | ret@0.4.3: 478 | resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} 479 | engines: {node: '>=10'} 480 | 481 | retimer@3.0.0: 482 | resolution: {integrity: sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==} 483 | 484 | reusify@1.0.4: 485 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 486 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 487 | 488 | rfdc@1.3.1: 489 | resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} 490 | 491 | safe-buffer@5.2.1: 492 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 493 | 494 | safe-regex2@3.1.0: 495 | resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} 496 | 497 | safe-stable-stringify@2.4.3: 498 | resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} 499 | engines: {node: '>=10'} 500 | 501 | secure-json-parse@2.7.0: 502 | resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} 503 | 504 | semver@7.6.0: 505 | resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} 506 | engines: {node: '>=10'} 507 | hasBin: true 508 | 509 | set-cookie-parser@2.6.0: 510 | resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} 511 | 512 | simple-swizzle@0.2.2: 513 | resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} 514 | 515 | sonic-boom@3.8.0: 516 | resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==} 517 | 518 | split2@4.2.0: 519 | resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 520 | engines: {node: '>= 10.x'} 521 | 522 | stack-trace@0.0.10: 523 | resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} 524 | 525 | string-width@4.2.3: 526 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 527 | engines: {node: '>=8'} 528 | 529 | string_decoder@1.3.0: 530 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 531 | 532 | strip-ansi@6.0.1: 533 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 534 | engines: {node: '>=8'} 535 | 536 | subarg@1.0.0: 537 | resolution: {integrity: sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==} 538 | 539 | supports-color@7.2.0: 540 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 541 | engines: {node: '>=8'} 542 | 543 | text-hex@1.0.0: 544 | resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} 545 | 546 | thread-stream@2.4.1: 547 | resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} 548 | 549 | timestring@6.0.0: 550 | resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==} 551 | engines: {node: '>=8'} 552 | 553 | tinybench@2.6.0: 554 | resolution: {integrity: sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==} 555 | 556 | toad-cache@3.7.0: 557 | resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} 558 | engines: {node: '>=12'} 559 | 560 | triple-beam@1.4.1: 561 | resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} 562 | engines: {node: '>= 14.0.0'} 563 | 564 | typescript@5.4.5: 565 | resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} 566 | engines: {node: '>=14.17'} 567 | hasBin: true 568 | 569 | underscore@1.13.6: 570 | resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} 571 | 572 | undici-types@5.26.5: 573 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 574 | 575 | uri-js@4.4.1: 576 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 577 | 578 | util-deprecate@1.0.2: 579 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 580 | 581 | uuid-parse@1.1.0: 582 | resolution: {integrity: sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==} 583 | 584 | uuid@8.3.2: 585 | resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} 586 | hasBin: true 587 | 588 | winston-transport@4.7.0: 589 | resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} 590 | engines: {node: '>= 12.0.0'} 591 | 592 | winston@3.12.0: 593 | resolution: {integrity: sha512-OwbxKaOlESDi01mC9rkM0dQqQt2I8DAUMRLZ/HpbwvDXm85IryEHgoogy5fziQy38PntgZsLlhAYHz//UPHZ5w==} 594 | engines: {node: '>= 12.0.0'} 595 | 596 | yallist@4.0.0: 597 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 598 | 599 | snapshots: 600 | 601 | '@assemblyscript/loader@0.19.23': {} 602 | 603 | '@babel/standalone@7.24.0': {} 604 | 605 | '@colors/colors@1.5.0': 606 | optional: true 607 | 608 | '@colors/colors@1.6.0': {} 609 | 610 | '@dabh/diagnostics@2.0.3': 611 | dependencies: 612 | colorspace: 1.1.4 613 | enabled: 2.0.0 614 | kuler: 2.0.0 615 | 616 | '@fastify/ajv-compiler@3.5.0': 617 | dependencies: 618 | ajv: 8.12.0 619 | ajv-formats: 2.1.1(ajv@8.12.0) 620 | fast-uri: 2.3.0 621 | 622 | '@fastify/error@3.4.1': {} 623 | 624 | '@fastify/fast-json-stringify-compiler@4.3.0': 625 | dependencies: 626 | fast-json-stringify: 5.12.0 627 | 628 | '@fastify/merge-json-schemas@0.1.1': 629 | dependencies: 630 | fast-deep-equal: 3.1.3 631 | 632 | '@types/autocannon@7.12.5': 633 | dependencies: 634 | '@types/node': 20.12.12 635 | 636 | '@types/lodash@4.17.3': {} 637 | 638 | '@types/node@20.12.12': 639 | dependencies: 640 | undici-types: 5.26.5 641 | 642 | '@types/triple-beam@1.3.5': {} 643 | 644 | '@types/underscore@1.11.15': {} 645 | 646 | abort-controller@3.0.0: 647 | dependencies: 648 | event-target-shim: 5.0.1 649 | 650 | abstract-logging@2.0.1: {} 651 | 652 | ajv-formats@2.1.1(ajv@8.12.0): 653 | optionalDependencies: 654 | ajv: 8.12.0 655 | 656 | ajv@8.12.0: 657 | dependencies: 658 | fast-deep-equal: 3.1.3 659 | json-schema-traverse: 1.0.0 660 | require-from-string: 2.0.2 661 | uri-js: 4.4.1 662 | 663 | ansi-regex@5.0.1: {} 664 | 665 | ansi-styles@4.3.0: 666 | dependencies: 667 | color-convert: 2.0.1 668 | 669 | archy@1.0.0: {} 670 | 671 | async@3.2.5: {} 672 | 673 | asynckit@0.4.0: {} 674 | 675 | atomic-sleep@1.0.0: {} 676 | 677 | autocannon@7.15.0: 678 | dependencies: 679 | chalk: 4.1.2 680 | char-spinner: 1.0.1 681 | cli-table3: 0.6.3 682 | color-support: 1.1.3 683 | cross-argv: 2.0.0 684 | form-data: 4.0.0 685 | has-async-hooks: 1.0.0 686 | hdr-histogram-js: 3.0.0 687 | hdr-histogram-percentiles-obj: 3.0.0 688 | http-parser-js: 0.5.8 689 | hyperid: 3.2.0 690 | lodash.chunk: 4.2.0 691 | lodash.clonedeep: 4.5.0 692 | lodash.flatten: 4.4.0 693 | manage-path: 2.0.0 694 | on-net-listen: 1.1.2 695 | pretty-bytes: 5.6.0 696 | progress: 2.0.3 697 | reinterval: 1.1.0 698 | retimer: 3.0.0 699 | semver: 7.6.0 700 | subarg: 1.0.0 701 | timestring: 6.0.0 702 | 703 | avvio@8.3.0: 704 | dependencies: 705 | '@fastify/error': 3.4.1 706 | archy: 1.0.0 707 | debug: 4.3.4 708 | fastq: 1.17.1 709 | transitivePeerDependencies: 710 | - supports-color 711 | 712 | base64-js@1.5.1: {} 713 | 714 | bench-node@0.1.0: {} 715 | 716 | buffer@5.7.1: 717 | dependencies: 718 | base64-js: 1.5.1 719 | ieee754: 1.2.1 720 | 721 | buffer@6.0.3: 722 | dependencies: 723 | base64-js: 1.5.1 724 | ieee754: 1.2.1 725 | 726 | chalk@4.1.2: 727 | dependencies: 728 | ansi-styles: 4.3.0 729 | supports-color: 7.2.0 730 | 731 | char-spinner@1.0.1: {} 732 | 733 | cli-table3@0.6.3: 734 | dependencies: 735 | string-width: 4.2.3 736 | optionalDependencies: 737 | '@colors/colors': 1.5.0 738 | 739 | color-convert@1.9.3: 740 | dependencies: 741 | color-name: 1.1.3 742 | 743 | color-convert@2.0.1: 744 | dependencies: 745 | color-name: 1.1.4 746 | 747 | color-name@1.1.3: {} 748 | 749 | color-name@1.1.4: {} 750 | 751 | color-string@1.9.1: 752 | dependencies: 753 | color-name: 1.1.4 754 | simple-swizzle: 0.2.2 755 | 756 | color-support@1.1.3: {} 757 | 758 | color@3.2.1: 759 | dependencies: 760 | color-convert: 1.9.3 761 | color-string: 1.9.1 762 | 763 | colorspace@1.1.4: 764 | dependencies: 765 | color: 3.2.1 766 | text-hex: 1.0.0 767 | 768 | combined-stream@1.0.8: 769 | dependencies: 770 | delayed-stream: 1.0.0 771 | 772 | cookie@0.6.0: {} 773 | 774 | cross-argv@2.0.0: {} 775 | 776 | debug@4.3.4: 777 | dependencies: 778 | ms: 2.1.2 779 | 780 | delayed-stream@1.0.0: {} 781 | 782 | dotenv@16.4.5: {} 783 | 784 | emoji-regex@8.0.0: {} 785 | 786 | enabled@2.0.0: {} 787 | 788 | event-target-shim@5.0.1: {} 789 | 790 | events@3.3.0: {} 791 | 792 | fast-content-type-parse@1.1.0: {} 793 | 794 | fast-decode-uri-component@1.0.1: {} 795 | 796 | fast-deep-equal@3.1.3: {} 797 | 798 | fast-json-stringify@5.12.0: 799 | dependencies: 800 | '@fastify/merge-json-schemas': 0.1.1 801 | ajv: 8.12.0 802 | ajv-formats: 2.1.1(ajv@8.12.0) 803 | fast-deep-equal: 3.1.3 804 | fast-uri: 2.3.0 805 | json-schema-ref-resolver: 1.0.1 806 | rfdc: 1.3.1 807 | 808 | fast-querystring@1.1.2: 809 | dependencies: 810 | fast-decode-uri-component: 1.0.1 811 | 812 | fast-redact@3.3.0: {} 813 | 814 | fast-uri@2.3.0: {} 815 | 816 | fastify@4.26.1: 817 | dependencies: 818 | '@fastify/ajv-compiler': 3.5.0 819 | '@fastify/error': 3.4.1 820 | '@fastify/fast-json-stringify-compiler': 4.3.0 821 | abstract-logging: 2.0.1 822 | avvio: 8.3.0 823 | fast-content-type-parse: 1.1.0 824 | fast-json-stringify: 5.12.0 825 | find-my-way: 8.2.2 826 | light-my-request: 5.11.1 827 | pino: 8.19.0 828 | process-warning: 3.0.0 829 | proxy-addr: 2.0.7 830 | rfdc: 1.3.1 831 | secure-json-parse: 2.7.0 832 | semver: 7.6.0 833 | toad-cache: 3.7.0 834 | transitivePeerDependencies: 835 | - supports-color 836 | 837 | fastq@1.17.1: 838 | dependencies: 839 | reusify: 1.0.4 840 | 841 | fecha@4.2.3: {} 842 | 843 | find-my-way@8.2.2: 844 | dependencies: 845 | fast-deep-equal: 3.1.3 846 | fast-querystring: 1.1.2 847 | safe-regex2: 3.1.0 848 | 849 | fn.name@1.1.0: {} 850 | 851 | form-data@4.0.0: 852 | dependencies: 853 | asynckit: 0.4.0 854 | combined-stream: 1.0.8 855 | mime-types: 2.1.35 856 | 857 | forwarded@0.2.0: {} 858 | 859 | has-async-hooks@1.0.0: {} 860 | 861 | has-flag@4.0.0: {} 862 | 863 | hdr-histogram-js@3.0.0: 864 | dependencies: 865 | '@assemblyscript/loader': 0.19.23 866 | base64-js: 1.5.1 867 | pako: 1.0.11 868 | 869 | hdr-histogram-percentiles-obj@3.0.0: {} 870 | 871 | http-parser-js@0.5.8: {} 872 | 873 | hyperid@3.2.0: 874 | dependencies: 875 | buffer: 5.7.1 876 | uuid: 8.3.2 877 | uuid-parse: 1.1.0 878 | 879 | ieee754@1.2.1: {} 880 | 881 | inherits@2.0.4: {} 882 | 883 | ipaddr.js@1.9.1: {} 884 | 885 | is-arrayish@0.3.2: {} 886 | 887 | is-fullwidth-code-point@3.0.0: {} 888 | 889 | is-stream@2.0.1: {} 890 | 891 | json-schema-ref-resolver@1.0.1: 892 | dependencies: 893 | fast-deep-equal: 3.1.3 894 | 895 | json-schema-traverse@1.0.0: {} 896 | 897 | kuler@2.0.0: {} 898 | 899 | light-my-request@5.11.1: 900 | dependencies: 901 | cookie: 0.6.0 902 | process-warning: 2.3.2 903 | set-cookie-parser: 2.6.0 904 | 905 | lodash.chunk@4.2.0: {} 906 | 907 | lodash.clonedeep@4.5.0: {} 908 | 909 | lodash.flatten@4.4.0: {} 910 | 911 | lodash@4.17.21: {} 912 | 913 | logform@2.6.0: 914 | dependencies: 915 | '@colors/colors': 1.6.0 916 | '@types/triple-beam': 1.3.5 917 | fecha: 4.2.3 918 | ms: 2.1.2 919 | safe-stable-stringify: 2.4.3 920 | triple-beam: 1.4.1 921 | 922 | lru-cache@6.0.0: 923 | dependencies: 924 | yallist: 4.0.0 925 | 926 | manage-path@2.0.0: {} 927 | 928 | mime-db@1.52.0: {} 929 | 930 | mime-types@2.1.35: 931 | dependencies: 932 | mime-db: 1.52.0 933 | 934 | minimist@1.2.8: {} 935 | 936 | moment@2.30.1: {} 937 | 938 | ms@2.1.2: {} 939 | 940 | nice-napi@1.0.2: 941 | dependencies: 942 | node-addon-api: 3.2.1 943 | node-gyp-build: 4.8.0 944 | optional: true 945 | 946 | node-addon-api@3.2.1: 947 | optional: true 948 | 949 | node-gyp-build@4.8.0: 950 | optional: true 951 | 952 | on-exit-leak-free@2.1.2: {} 953 | 954 | on-net-listen@1.1.2: {} 955 | 956 | one-time@1.0.0: 957 | dependencies: 958 | fn.name: 1.1.0 959 | 960 | pako@1.0.11: {} 961 | 962 | pino-abstract-transport@1.1.0: 963 | dependencies: 964 | readable-stream: 4.5.2 965 | split2: 4.2.0 966 | 967 | pino-std-serializers@6.2.2: {} 968 | 969 | pino@8.19.0: 970 | dependencies: 971 | atomic-sleep: 1.0.0 972 | fast-redact: 3.3.0 973 | on-exit-leak-free: 2.1.2 974 | pino-abstract-transport: 1.1.0 975 | pino-std-serializers: 6.2.2 976 | process-warning: 3.0.0 977 | quick-format-unescaped: 4.0.4 978 | real-require: 0.2.0 979 | safe-stable-stringify: 2.4.3 980 | sonic-boom: 3.8.0 981 | thread-stream: 2.4.1 982 | 983 | piscina@4.4.0: 984 | optionalDependencies: 985 | nice-napi: 1.0.2 986 | 987 | prettier@3.2.5: {} 988 | 989 | pretty-bytes@5.6.0: {} 990 | 991 | process-warning@2.3.2: {} 992 | 993 | process-warning@3.0.0: {} 994 | 995 | process@0.11.10: {} 996 | 997 | progress@2.0.3: {} 998 | 999 | proxy-addr@2.0.7: 1000 | dependencies: 1001 | forwarded: 0.2.0 1002 | ipaddr.js: 1.9.1 1003 | 1004 | punycode@2.3.1: {} 1005 | 1006 | quick-format-unescaped@4.0.4: {} 1007 | 1008 | readable-stream@3.6.2: 1009 | dependencies: 1010 | inherits: 2.0.4 1011 | string_decoder: 1.3.0 1012 | util-deprecate: 1.0.2 1013 | 1014 | readable-stream@4.5.2: 1015 | dependencies: 1016 | abort-controller: 3.0.0 1017 | buffer: 6.0.3 1018 | events: 3.3.0 1019 | process: 0.11.10 1020 | string_decoder: 1.3.0 1021 | 1022 | real-require@0.2.0: {} 1023 | 1024 | reinterval@1.1.0: {} 1025 | 1026 | require-from-string@2.0.2: {} 1027 | 1028 | ret@0.4.3: {} 1029 | 1030 | retimer@3.0.0: {} 1031 | 1032 | reusify@1.0.4: {} 1033 | 1034 | rfdc@1.3.1: {} 1035 | 1036 | safe-buffer@5.2.1: {} 1037 | 1038 | safe-regex2@3.1.0: 1039 | dependencies: 1040 | ret: 0.4.3 1041 | 1042 | safe-stable-stringify@2.4.3: {} 1043 | 1044 | secure-json-parse@2.7.0: {} 1045 | 1046 | semver@7.6.0: 1047 | dependencies: 1048 | lru-cache: 6.0.0 1049 | 1050 | set-cookie-parser@2.6.0: {} 1051 | 1052 | simple-swizzle@0.2.2: 1053 | dependencies: 1054 | is-arrayish: 0.3.2 1055 | 1056 | sonic-boom@3.8.0: 1057 | dependencies: 1058 | atomic-sleep: 1.0.0 1059 | 1060 | split2@4.2.0: {} 1061 | 1062 | stack-trace@0.0.10: {} 1063 | 1064 | string-width@4.2.3: 1065 | dependencies: 1066 | emoji-regex: 8.0.0 1067 | is-fullwidth-code-point: 3.0.0 1068 | strip-ansi: 6.0.1 1069 | 1070 | string_decoder@1.3.0: 1071 | dependencies: 1072 | safe-buffer: 5.2.1 1073 | 1074 | strip-ansi@6.0.1: 1075 | dependencies: 1076 | ansi-regex: 5.0.1 1077 | 1078 | subarg@1.0.0: 1079 | dependencies: 1080 | minimist: 1.2.8 1081 | 1082 | supports-color@7.2.0: 1083 | dependencies: 1084 | has-flag: 4.0.0 1085 | 1086 | text-hex@1.0.0: {} 1087 | 1088 | thread-stream@2.4.1: 1089 | dependencies: 1090 | real-require: 0.2.0 1091 | 1092 | timestring@6.0.0: {} 1093 | 1094 | tinybench@2.6.0: {} 1095 | 1096 | toad-cache@3.7.0: {} 1097 | 1098 | triple-beam@1.4.1: {} 1099 | 1100 | typescript@5.4.5: {} 1101 | 1102 | underscore@1.13.6: {} 1103 | 1104 | undici-types@5.26.5: {} 1105 | 1106 | uri-js@4.4.1: 1107 | dependencies: 1108 | punycode: 2.3.1 1109 | 1110 | util-deprecate@1.0.2: {} 1111 | 1112 | uuid-parse@1.1.0: {} 1113 | 1114 | uuid@8.3.2: {} 1115 | 1116 | winston-transport@4.7.0: 1117 | dependencies: 1118 | logform: 2.6.0 1119 | readable-stream: 3.6.2 1120 | triple-beam: 1.4.1 1121 | 1122 | winston@3.12.0: 1123 | dependencies: 1124 | '@colors/colors': 1.6.0 1125 | '@dabh/diagnostics': 2.0.3 1126 | async: 3.2.5 1127 | is-stream: 2.0.1 1128 | logform: 2.6.0 1129 | one-time: 1.0.0 1130 | readable-stream: 3.6.2 1131 | safe-stable-stringify: 2.4.3 1132 | stack-trace: 0.0.10 1133 | triple-beam: 1.4.1 1134 | winston-transport: 4.7.0 1135 | 1136 | yallist@4.0.0: {} 1137 | -------------------------------------------------------------------------------- /src/babel-benchmark.js: -------------------------------------------------------------------------------- 1 | const fs = require('node:fs'); 2 | const path = require('node:path'); 3 | const assert = require('node:assert'); 4 | const Babel = require('@babel/standalone'); 5 | 6 | const payloads = [ 7 | 'lodash.fp.js', 8 | ].map((file) => fs.readFileSync(path.join(__dirname, '..', 'fixtures', file), 'utf8')); 9 | 10 | module.exports = { 11 | name: 'babel', 12 | type: 'operation', 13 | operations: [ 14 | { 15 | name: 'transform (code=true ast=true)', 16 | fn: () => { 17 | let v = undefined; 18 | for (const p of payloads) { 19 | v = Babel.transform(p, { code: true, ast: true }).code; 20 | assert.ok(v) 21 | } 22 | return v; 23 | }, 24 | }, 25 | { 26 | name: 'transform (code=false)', 27 | fn: () => { 28 | let v = undefined; 29 | for (const p of payloads) { 30 | v = Babel.transform(p, { code: false }); 31 | assert.ok(v); 32 | } 33 | return v; 34 | }, 35 | } 36 | ], 37 | benchmarker: 'tinybench', 38 | }; 39 | -------------------------------------------------------------------------------- /src/dotenv-benchmark.js: -------------------------------------------------------------------------------- 1 | const path = require('node:path'); 2 | const dotenv = require('dotenv'); 3 | 4 | const envFile = path.join(__dirname, '..', 'fixtures', '.env.sample'); 5 | 6 | module.exports = { 7 | name: 'dotenv', 8 | type: 'operation', 9 | operations: [ 10 | { 11 | name: 'config', 12 | fn: () => { 13 | return dotenv.config({ path: envFile }); 14 | }, 15 | }, 16 | ], 17 | benchmarker: 'bench-node', 18 | }; 19 | -------------------------------------------------------------------------------- /src/fastify-benchmark-disabled.js: -------------------------------------------------------------------------------- 1 | const path = require('node:path'); 2 | module.exports = { 3 | name: 'fastify', 4 | type: 'http', 5 | http: { 6 | server: path.join(__dirname, './fastify-server.js'), 7 | serverPort: 3000, 8 | routes: [ 9 | { path: '/', method: 'GET' }, 10 | { path: '/schema', method: 'GET' }, 11 | ], 12 | }, 13 | benchmarker: 'autocannon', 14 | }; 15 | -------------------------------------------------------------------------------- /src/fastify-server.js: -------------------------------------------------------------------------------- 1 | const Fastify = require('fastify'); 2 | 3 | const app = Fastify({ logger: false }); 4 | 5 | app.get('/', (req, reply) => { 6 | reply.send({ hello: 'world' }); 7 | }); 8 | 9 | const schema = { 10 | response: { 11 | default: { 12 | type: 'object', 13 | properties: { 14 | hello: { 15 | type: 'string', 16 | } 17 | } 18 | }, 19 | }, 20 | }; 21 | 22 | app.get('/schema', schema, (req, reply) => { 23 | reply.send({ hello: 'world' }); 24 | }); 25 | 26 | app.listen({ port: 3000 }, (err, server) => { 27 | if (err) throw err; 28 | }) 29 | -------------------------------------------------------------------------------- /src/lodash-benchmark.js: -------------------------------------------------------------------------------- 1 | const assert = require('node:assert'); 2 | const lodash = require('lodash'); 3 | 4 | module.exports = { 5 | name: 'lodash', 6 | type: 'operation', 7 | operations: [ 8 | { 9 | name: '.chunk', 10 | fn: () => { 11 | assert.ok(lodash.chunk(['a', 'b', 'c', 'd'], 2)); 12 | }, 13 | }, 14 | { 15 | name: '.groupBy', 16 | fn: () => { 17 | assert.ok(lodash.groupBy([6.1, 4.2, 6.3], Math.floor)); 18 | }, 19 | }, 20 | { 21 | name: '.includes', 22 | fn: () => { 23 | assert.ok(lodash.includes({ 'a': 1, 'b': 2 }, 1)); 24 | }, 25 | }, 26 | { 27 | name: '.orderBy', 28 | fn: () => { 29 | const users = [ 30 | { 'user': 'fred', 'age': 48 }, 31 | { 'user': 'barney', 'age': 34 }, 32 | { 'user': 'fred', 'age': 40 }, 33 | { 'user': 'barney', 'age': 36 } 34 | ]; 35 | assert.ok(lodash.orderBy(users, ['user', 'age'], ['asc', 'desc'])); 36 | } 37 | } 38 | ], 39 | benchmarker: 'bench-node', 40 | }; 41 | -------------------------------------------------------------------------------- /src/moment-benchmark.js: -------------------------------------------------------------------------------- 1 | const assert = require('node:assert'); 2 | const moment = require('moment'); 3 | 4 | module.exports = { 5 | name: 'moment', 6 | type: 'operation', 7 | operations: [ 8 | { 9 | name: 'format (full)', 10 | fn: () => { 11 | assert.ok(moment().format('MMMM Do YYYY, h:mm:ss a')); 12 | }, 13 | }, 14 | { 15 | name: 'format', 16 | fn: () => { 17 | assert.ok(moment().format()); 18 | }, 19 | }, 20 | { 21 | name: 'fromNow (YYYYMMDD)', 22 | fn: () => { 23 | assert.ok(moment('20111031', 'YYYYMMDD').fromNow()); 24 | }, 25 | }, 26 | { 27 | name: 'subtract (10)', 28 | fn: () => { 29 | assert.ok(moment().subtract(10, 'days').calendar()); 30 | }, 31 | }, 32 | ], 33 | benchmarker: 'bench-node', 34 | }; 35 | -------------------------------------------------------------------------------- /src/pino-benchmark.js: -------------------------------------------------------------------------------- 1 | const pino = require('pino'); 2 | const logger = pino(pino.destination('/dev/null')); 3 | 4 | module.exports = { 5 | name: 'pinojs', 6 | type: 'operation', 7 | operations: [ 8 | { 9 | name: 'info (10x)', 10 | fn: () => { 11 | for (let i = 0; i < 10; ++i) { 12 | logger.info('hello world'); 13 | } 14 | }, 15 | }, 16 | ], 17 | benchmarker: 'bench-node', 18 | }; 19 | -------------------------------------------------------------------------------- /src/prettier-benchmark.js: -------------------------------------------------------------------------------- 1 | const fs = require('node:fs'); 2 | const path = require('node:path'); 3 | const assert = require('node:assert'); 4 | const prettier = require('prettier'); 5 | 6 | const payloads = [ 7 | 'lodash.fp.js', 8 | ].map((file) => fs.readFileSync(path.join(__dirname, '..', 'fixtures', file), 'utf8')); 9 | 10 | module.exports = { 11 | name: 'prettier', 12 | type: 'operation', 13 | operations: [ 14 | { 15 | name: 'format', 16 | fn: () => { 17 | let v = undefined; 18 | for (const p of payloads) { 19 | v = prettier.format(p, { parser: 'babel' }); 20 | assert.ok(v); 21 | } 22 | return v; 23 | }, 24 | }, 25 | { 26 | name: 'format (singleQuote=true useTabs=true)', 27 | fn: () => { 28 | let v = undefined; 29 | for (const p of payloads) { 30 | v = prettier.format( 31 | p, 32 | { singleQuote: true, useTabs: true, parser: 'babel' }, 33 | ); 34 | assert.ok(v); 35 | } 36 | return v; 37 | }, 38 | }, 39 | { 40 | name: 'format (semi=false)', 41 | fn: () => { 42 | let v = undefined; 43 | for (const p of payloads) { 44 | v = prettier.format( 45 | p, 46 | { semi: false, parser: 'babel' } 47 | ); 48 | assert.ok(v); 49 | } 50 | return v; 51 | }, 52 | }, 53 | ], 54 | benchmarker: 'tinybench', 55 | }; 56 | -------------------------------------------------------------------------------- /src/typescript-benchmark.js: -------------------------------------------------------------------------------- 1 | const fs = require('node:fs'); 2 | const ts = require('typescript'); 3 | const path = require('node:path'); 4 | const assert = require('node:assert'); 5 | 6 | const filePath = path.join(__dirname, '..', 'fixtures', 'ts-sample.ts'); 7 | const code = fs.readFileSync(filePath, 'utf8'); 8 | 9 | module.exports = { 10 | name: 'typescript', 11 | type: 'operation', 12 | operations: [ 13 | { 14 | name: 'transpile', 15 | fn: () => { 16 | const r = ts.transpile( 17 | code, 18 | { 19 | // CJS Settings 20 | target: ts.ScriptTarget.ESNext, 21 | module: ts.ModuleKind.CommonJS, 22 | moduleResolution: ts.ModuleResolutionKind.Node, 23 | 24 | // Avoid writing to disk 25 | noEmit: true, 26 | 27 | // Avoids any checking related code 28 | checkJs: false, 29 | strict: false, 30 | isolatedModules: true, 31 | skipDefaultLibCheck: true, 32 | skipLibCheck: true, 33 | }, 34 | filePath, 35 | ); 36 | assert.ok(r); 37 | }, 38 | }, 39 | { 40 | name: 'createSourceFile', 41 | fn: () => { 42 | const r = ts.createSourceFile( 43 | filePath, 44 | code, 45 | ts.ScriptTarget.ESNext, 46 | false, 47 | ts.ScriptKind.TS, 48 | ); 49 | assert.ok(r); 50 | }, 51 | }, 52 | { 53 | name: 'getSemanticDiagnostics', 54 | fn: () => { 55 | const program = ts.createProgram({ 56 | rootNames: [filePath], 57 | options: { 58 | // CJS Settings 59 | target: ts.ScriptTarget.ESNext, 60 | module: ts.ModuleKind.CommonJS, 61 | moduleResolution: ts.ModuleResolutionKind.Node, 62 | 63 | // also loads and checks js 64 | allowJs: true, 65 | checkJs: true, 66 | 67 | // test types 68 | strict: true, 69 | 70 | // Avoid writing to disk 71 | noEmit: true, 72 | 73 | // Loads external files 74 | isolatedModules: true, 75 | skipDefaultLibCheck: false, 76 | skipLibCheck: false, 77 | }, 78 | }); 79 | 80 | program.getSemanticDiagnostics(program.getSourceFile(filePath)); 81 | }, 82 | }, 83 | ], 84 | benchmarker: 'tinybench', 85 | }; 86 | -------------------------------------------------------------------------------- /src/underscore-benchmark.js: -------------------------------------------------------------------------------- 1 | const underscore = require('underscore'); 2 | const assert = require('node:assert'); 3 | 4 | module.exports = { 5 | name: 'underscore', 6 | type: 'operation', 7 | operations: [ 8 | { 9 | name: '.chunk', 10 | fn: () => { 11 | assert.ok(underscore.chunk(['a', 'b', 'c', 'd'], 2)); 12 | }, 13 | }, 14 | { 15 | name: '.groupBy', 16 | fn: () => { 17 | assert.ok(underscore.groupBy([6.1, 4.2, 6.3], Math.floor)); 18 | }, 19 | }, 20 | { 21 | name: '.includes', 22 | fn: () => { 23 | assert.ok(underscore.includes({ 'a': 1, 'b': 2 }, 1)); 24 | }, 25 | }, 26 | { 27 | name: '.orderBy', 28 | fn: () => { 29 | const users = [ 30 | { 'user': 'fred', 'age': 48 }, 31 | { 'user': 'barney', 'age': 34 }, 32 | { 'user': 'fred', 'age': 40 }, 33 | { 'user': 'barney', 'age': 36 } 34 | ]; 35 | assert.ok(underscore.sortBy(users, ['user', 'age'], ['asc', 'desc'])); 36 | } 37 | } 38 | ], 39 | benchmarker: 'bench-node', 40 | }; 41 | -------------------------------------------------------------------------------- /src/winston-benchmark.js: -------------------------------------------------------------------------------- 1 | const fs = require('node:fs'); 2 | const winston = require('winston'); 3 | 4 | const logger = winston.createLogger({ 5 | transports: [ 6 | new winston.transports.Stream({ 7 | stream: fs.createWriteStream('/dev/null'), 8 | }), 9 | ], 10 | }); 11 | 12 | module.exports = { 13 | name: 'winston', 14 | type: 'operation', 15 | operations: [ 16 | { 17 | name: 'info (10x)', 18 | fn: () => { 19 | for (let i = 0; i < 10; ++i) { 20 | logger.log('info', 'hello world'); 21 | } 22 | }, 23 | }, 24 | ], 25 | benchmarker: 'bench-node', 26 | }; 27 | -------------------------------------------------------------------------------- /worker.js: -------------------------------------------------------------------------------- 1 | const { spawn } = require('node:child_process'); 2 | const assert = require('node:assert'); 3 | 4 | const autocannon = require('autocannon'); 5 | const { Bench } = require('tinybench'); 6 | const { Suite } = require('bench-node'); 7 | 8 | const { setTimeout: delay } = require('node:timers/promises'); 9 | 10 | const runner = { 11 | autocannon: async (opts, aggregated) => { 12 | if (!aggregated.sortKey) { 13 | aggregated.sortKey = 'requests' 14 | } 15 | 16 | const url = `http://localhost:${opts.http.serverPort}` 17 | const results = await autocannon({ 18 | url, 19 | connections: 100, 20 | pipelining: 1, 21 | duration: 10 * opts.http.routes.length, 22 | requests: opts.http.routes, 23 | }) 24 | if (!aggregated[url]) { 25 | aggregated[url] = [results] 26 | } else { 27 | aggregated[url].push(results) 28 | } 29 | }, 30 | 'bench-node': async (opts, aggregated) => { 31 | if (!aggregated.sortKey) { 32 | aggregated.sortKey = 'opsSec' 33 | } 34 | 35 | const suite = new Suite({ reporter: false }); 36 | 37 | for (const operation of opts.operations) { 38 | suite.add(operation.name, operation.fn); 39 | } 40 | 41 | const results = await suite.run(); 42 | for (const result of results) { 43 | if (!aggregated[result.name]) { 44 | aggregated[result.name] = [{ 45 | opsSec: result.opsSec, 46 | samples: result.iterations, 47 | sd: '', 48 | variance: '', 49 | }] 50 | } else { 51 | aggregated[result.name].push({ 52 | opsSec: result.opsSec, 53 | samples: result.iterations, 54 | sd: '', 55 | variance: '', 56 | }) 57 | } 58 | } 59 | }, 60 | tinybench: async (opts, aggregated) => { 61 | if (!aggregated.sortKey) { 62 | aggregated.sortKey = 'opsSec' 63 | } 64 | 65 | const suite = new Bench({ time: 100 }); 66 | 67 | for (const operation of opts.operations) { 68 | suite.add(operation.name, operation.fn); 69 | } 70 | await suite.warmup(); 71 | await suite.run(); 72 | const tasks = suite.tasks; 73 | for (const task of tasks) { 74 | const result = task.result 75 | if (!aggregated[task.name]) { 76 | aggregated[task.name] = [{ 77 | opsSec: result.hz, 78 | samples: result.samples.length, 79 | sd: result.sd, 80 | variance: result.variance, 81 | }] 82 | } else { 83 | aggregated[task.name].push({ 84 | opsSec: result.hz, 85 | samples: result.samples.length, 86 | sd: result.sd, 87 | variance: result.variance, 88 | }) 89 | } 90 | } 91 | }, 92 | } 93 | 94 | const parser = { 95 | autocannon: (settings, result) => { 96 | return { 97 | name: settings.name, 98 | method: 'autocannon', 99 | http: { 100 | totalReq: asNumber(result.requests), 101 | duration: result.duration, 102 | errors: result.errors, 103 | } 104 | }; 105 | }, 106 | tinybench: (settings, result) => { 107 | return { 108 | name: settings.name, 109 | method: 'tinybench', 110 | operations: result, 111 | } 112 | }, 113 | 'bench-node': (settings, result) => { 114 | return { 115 | name: settings.name, 116 | method: 'bench-node', 117 | operations: result, 118 | } 119 | } 120 | } 121 | 122 | const ALLOWED_BENCHMARKER = ['autocannon', 'tinybench', 'bench-node']; 123 | 124 | function asNumber (stat) { 125 | const result = Object.create(null) 126 | for (const k of Object.keys(stat)) { 127 | result[k] = stat[k].toLocaleString(undefined, { 128 | // to show all digits 129 | maximumFractionDigits: 20 130 | }) 131 | } 132 | return result 133 | } 134 | 135 | function spawnServer(settings) { 136 | const server = spawn( 137 | process.execPath, 138 | [settings.http.server], 139 | { stdio: 'inherit' }, 140 | ); 141 | return server; 142 | } 143 | 144 | function findMedian(aggregated) { 145 | const results = [] 146 | // Select median 147 | const sortKey = aggregated.sortKey 148 | for (const k of Object.keys(aggregated)) { 149 | if (aggregated[k] === sortKey) continue 150 | aggregated[k].sort((a, b) => a[sortKey] > b[sortKey]) 151 | const middleIndex = Math.floor(aggregated[k].length / 2); 152 | results.push({ 153 | name: k, 154 | ...aggregated[k][middleIndex] 155 | }) 156 | } 157 | return results 158 | } 159 | 160 | async function runBenchmark(settings) { 161 | assert.ok(ALLOWED_BENCHMARKER.includes(settings.benchmarker), 'Invalid settings.benchmarker'); 162 | 163 | let server = undefined; 164 | if (settings.type === 'http') { 165 | assert.ok(settings.http.server, 'HTTP Benchmark must have a server to be spawned'); 166 | server = spawnServer(settings); 167 | // TODO: replace this workaround to use IPC to know when server is up 168 | await delay(1000); 169 | } 170 | const benchRunner = runner[settings.benchmarker]; 171 | const benchParser = parser[settings.benchmarker]; 172 | 173 | const aggregated = {}; 174 | for (let i = 0; i < 10; ++i) { 175 | await benchRunner(settings, aggregated) 176 | } 177 | const results = findMedian(aggregated) 178 | if (server) { 179 | server.kill('SIGINT'); 180 | } 181 | return benchParser(settings, results); 182 | } 183 | 184 | async function main (benchFile) { 185 | const bench = require(benchFile); 186 | const result = await runBenchmark(bench); 187 | return result; 188 | } 189 | 190 | module.exports = main; 191 | --------------------------------------------------------------------------------