From 4072dc6f0a3879192ce86c6cc80736b8595e872f Mon Sep 17 00:00:00 2001 From: oxmc <67136658+oxmc@users.noreply.github.com> Date: Sun, 7 Dec 2025 01:30:14 -0800 Subject: [PATCH] Update to eslint --- .eslintrc.json | 33 + package-lock.json | 1328 +++++++++++++++++++++++++------ package.json | 10 +- src/compiler.ts | 299 +++---- src/fs/SnapshotZipFS.ts | 433 +++++----- src/fs/bundle.ts | 47 +- src/fs/patch.ts | 151 ++-- src/logger.ts | 76 +- src/nexe.ts | 50 +- src/options.ts | 321 ++++---- src/patches/boot-nexe.ts | 62 +- src/patches/build-fixes.ts | 21 +- src/patches/disable-node-cli.ts | 71 +- src/patches/flags.ts | 19 +- src/patches/gyp.ts | 12 +- src/patches/ico.ts | 22 +- src/patches/index.ts | 20 +- src/patches/node-rc.ts | 31 +- src/patches/snapshot.ts | 25 +- src/patches/third-party-main.ts | 131 +-- src/releases.ts | 73 +- src/steps/artifacts.ts | 74 +- src/steps/bundle.ts | 95 ++- src/steps/clean.ts | 31 +- src/steps/cli.ts | 70 +- src/steps/download.ts | 147 ++-- src/steps/mach-o.ts | 48 +- src/steps/resource.ts | 42 +- src/steps/shim.ts | 35 +- src/target.ts | 111 +-- src/types.d.ts | 26 +- src/util.ts | 80 +- tasks/build.ts | 159 ++-- tasks/docker.ts | 56 +- tasks/post-build.ts | 32 +- tslint.json | 9 - 36 files changed, 2696 insertions(+), 1554 deletions(-) create mode 100644 .eslintrc.json delete mode 100644 tslint.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..df64da7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "plugins": ["@typescript-eslint", "prettier"], + "rules": { + "prettier/prettier": "warn", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-non-null-assertion": "warn", + "@typescript-eslint/no-empty-function": "warn", + "no-useless-escape": "warn", + "no-empty": "warn", + "no-constant-condition": "warn", + "prefer-const": "warn" + }, + "env": { + "node": true, + "es6": true + }, + "ignorePatterns": ["lib/", "node_modules/", "*.js", "webpack.config.ts"] +} diff --git a/package-lock.json b/package-lock.json index 7c51804..b821a60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,15 +44,17 @@ "@types/ora": "^3.2.0", "@types/rimraf": "3.0.2", "@types/semver": "^7.3.13", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", "chai": "^4.3.7", + "eslint": "^8.40.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", "execa": "^5.1.1", "lodash": "^4.17.21", "mocha": "^10.2.0", "prettier": "^2.8.7", "ts-node": "^10.9.1", - "tslint": "^6.1.1", - "tslint-config-prettier": "^1.18.0", - "tslint-plugin-prettier": "^2.3.0", "typescript": "^5.0.3", "webpack-cli": "^5.0.1" }, @@ -60,31 +62,6 @@ "node": ">=10" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@calebboyd/semaphore": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@calebboyd/semaphore/-/semaphore-1.3.1.tgz", @@ -113,6 +90,131 @@ "node": ">=10.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -482,6 +584,317 @@ "node": ">= 12" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -737,6 +1150,16 @@ "acorn": "^8.14.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", @@ -1130,16 +1553,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -1153,6 +1566,16 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -1538,6 +1961,13 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -1581,6 +2011,19 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1711,21 +2154,96 @@ "node": ">=0.8.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz", - "integrity": "sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", "dependencies": { - "fast-diff": "^1.1.1", - "jest-docblock": "^21.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=4.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", + "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "prettier": ">= 0.11.0" + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.5.tgz", + "integrity": "sha512-9Ni+xgemM2IWLq6aXEpP2+V/V30GeA/46Ar629vcMqVPodFFWC9skHu/D1phvuqtS8bJCFnNf01/qcmqYEwNfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, "node_modules/eslint-scope": { @@ -1741,18 +2259,234 @@ "node": ">=8.0.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, "node_modules/esrecurse": { @@ -1785,6 +2519,16 @@ "node": ">=4.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1847,6 +2591,20 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", @@ -1881,6 +2639,19 @@ "reusify": "^1.0.4" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1919,6 +2690,28 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -2112,6 +2905,22 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause" }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2150,6 +2959,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2280,6 +3096,33 @@ "node": ">= 4" } }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -2299,6 +3142,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2408,6 +3261,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2490,13 +3353,6 @@ "node": ">= 4" } }, - "node_modules/jest-docblock": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", - "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", - "dev": true, - "license": "MIT" - }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -2535,13 +3391,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, "node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", @@ -2555,6 +3404,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2567,6 +3423,23 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -2618,12 +3491,19 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } }, "node_modules/loader-runner": { "version": "4.3.1", @@ -2684,6 +3564,13 @@ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", @@ -3081,6 +3968,20 @@ "readable-stream": "^3.6.0" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3153,6 +4054,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", @@ -3223,6 +4142,19 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3366,6 +4298,16 @@ "node": ">=8" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -3382,6 +4324,19 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -3400,6 +4355,16 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3707,16 +4672,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -3822,13 +4777,6 @@ "source-map": "^0.6.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4057,6 +5005,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4240,151 +5195,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - } - }, - "node_modules/tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", - "dev": true, - "license": "MIT", - "bin": { - "tslint-config-prettier-check": "bin/check.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/tslint-plugin-prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-2.3.0.tgz", - "integrity": "sha512-F9e4K03yc9xuvv+A0v1EmjcnDwpz8SpCD8HzqSDe0eyg34cBinwn9JjmnnRrNAs4HdleRQj7qijp+P/JTxt4vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-plugin-prettier": "^2.2.0", - "lines-and-columns": "^1.1.6", - "tslib": "^1.7.1" - }, - "engines": { - "node": ">= 4" - }, - "peerDependencies": { - "prettier": "^1.9.0 || ^2.0.0", - "tslint": "^5.0.0 || ^6.0.0" - } - }, - "node_modules/tslint-plugin-prettier/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tslint/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/tslint/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslint/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/tslint/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/tslint/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -4397,6 +5207,19 @@ "node": "*" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", @@ -4407,6 +5230,19 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -4456,6 +5292,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", @@ -4716,6 +5562,16 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "license": "MIT" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", diff --git a/package.json b/package.json index d7a2b62..dc0914a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test:integration:run": "run-script-os", "test:integration:run:win32": "integration-tests.exe", "test:integration:run:default": "./integration-tests", - "lint": "tslint \"{src,plugins,tasks}/**/*.ts\" --fix", + "lint": "eslint \"{src,plugins,tasks}/**/*.ts\" --fix", "prepare": "npm run lint && npm run build && npm test", "prebuild": "rimraf lib", "build": "tsc --declaration && tsc -p tasks && webpack", @@ -82,9 +82,11 @@ "mocha": "^10.2.0", "prettier": "^2.8.7", "ts-node": "^10.9.1", - "tslint": "^6.1.1", - "tslint-config-prettier": "^1.18.0", - "tslint-plugin-prettier": "^2.3.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "eslint": "^8.40.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", "typescript": "^5.0.3", "webpack-cli": "^5.0.1" } diff --git a/src/compiler.ts b/src/compiler.ts index 3fae12e..34a0635 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1,8 +1,8 @@ -import { delimiter, resolve, normalize, join } from 'path' -import { Buffer } from 'buffer' -import { createReadStream, ReadStream } from 'fs' -import { spawn } from 'child_process' -import { Logger, LogStep } from './logger' +import { delimiter, resolve, normalize, join } from "path"; +import { Buffer } from "buffer"; +import { createReadStream, ReadStream } from "fs"; +import { spawn } from "child_process"; +import { Logger, LogStep } from "./logger"; import { readFileAsync, writeFileAsync, @@ -13,33 +13,33 @@ import { bound, semverGt, wrap, -} from './util' -import { NexeOptions, version } from './options' -import { NexeTarget } from './target' -import { PassThrough, Readable, Stream, Transform } from 'stream' -import MultiStream = require('multistream') -import { Bundle, toStream } from './fs/bundle' -import { File } from 'resolve-dependencies' -import { FactoryStream, LazyStream } from 'multistream' +} from "./util"; +import { NexeOptions, version } from "./options"; +import { NexeTarget } from "./target"; +import { PassThrough, Readable, Stream, Transform } from "stream"; +import MultiStream = require("multistream"); +import { Bundle, toStream } from "./fs/bundle"; +import { File } from "resolve-dependencies"; +import { FactoryStream, LazyStream } from "multistream"; -const isBsd = Boolean(~process.platform.indexOf('bsd')) -const make = isWindows ? 'vcbuild.bat' : isBsd ? 'gmake' : 'make' -const configure = isWindows ? 'configure' : './configure' +const isBsd = Boolean(~process.platform.indexOf("bsd")); +const make = isWindows ? "vcbuild.bat" : isBsd ? "gmake" : "make"; +const configure = isWindows ? "configure" : "./configure"; -type StringReplacer = (match: string) => string +type StringReplacer = (match: string) => string; export interface NexeFile { - filename: string - absPath: string - contents: string | Buffer + filename: string; + absPath: string; + contents: string | Buffer; } -export { NexeOptions } +export { NexeOptions }; export class NexeError extends Error { constructor(m: string) { - super(m) - Object.setPrototypeOf(this, NexeError.prototype) + super(m); + Object.setPrototypeOf(this, NexeError.prototype); } } @@ -47,283 +47,302 @@ export class NexeCompiler { /** * Epoch of when compilation started */ - private start = Date.now() - private compileStep: LogStep | undefined - public log = new Logger(this.options.loglevel) + private start = Date.now(); + private compileStep: LogStep | undefined; + public log = new Logger(this.options.loglevel); /** * Copy of process.env */ - public env = { ...process.env } + public env = { ...process.env }; /** * Virtual FileSystem */ - public bundle: Bundle + public bundle: Bundle; /** * Root directory for the source of the current build */ - public src: string + public src: string; /** * In memory files that are being manipulated by the compiler */ - public files: NexeFile[] = [] + public files: NexeFile[] = []; /** * Standalone pieces of code run before the application entrypoint */ - public shims: string[] = [] + public shims: string[] = []; /** * The last shim (defaults to "require('module').runMain()") */ - public startup: string = '' + public startup = ""; /** * The main entrypoint filename for your application - eg. node mainFile.js */ - public entrypoint: string | undefined + public entrypoint: string | undefined; /** * Not used */ - public targets: NexeTarget[] + public targets: NexeTarget[]; /** * Current target of the compiler */ - public target: NexeTarget + public target: NexeTarget; /** * Output filename (-o myapp.exe) */ - public output = this.options.output + public output = this.options.output; /** * Flag to indicate whether or notstdin was used for input */ - public stdinUsed = false + public stdinUsed = false; /** * Path to the configure script */ - public configureScript: string + public configureScript: string; /** * The file path of node binary */ - public nodeSrcBinPath: string + public nodeSrcBinPath: string; /** * Remote asset path if available */ - public remoteAsset: string + public remoteAsset: string; constructor(public options: NexeOptions) { - const { python } = (this.options = options) + const { python } = (this.options = options); //SOMEDAY iterate over multiple targets with `--outDir` - this.targets = options.targets as NexeTarget[] - this.target = this.targets[0] + this.targets = options.targets as NexeTarget[]; + this.target = this.targets[0]; if (!/https?\:\/\//.test(options.remote)) { - throw new NexeError(`Invalid remote URI scheme (must be http or https): ${options.remote}`) + throw new NexeError( + `Invalid remote URI scheme (must be http or https): ${options.remote}` + ); } - this.remoteAsset = options.remote + this.target.toString() - this.src = join(this.options.temp, this.target.version) - this.configureScript = configure + (semverGt(this.target.version, '10.10.0') ? '.py' : '') + this.remoteAsset = options.remote + this.target.toString(); + this.src = join(this.options.temp, this.target.version); + this.configureScript = + configure + (semverGt(this.target.version, "10.10.0") ? ".py" : ""); this.nodeSrcBinPath = isWindows - ? join(this.src, 'Release', 'node.exe') - : join(this.src, 'out', 'Release', 'node') - this.log.step('nexe ' + version, 'info') - this.bundle = new Bundle(options) + ? join(this.src, "Release", "node.exe") + : join(this.src, "out", "Release", "node"); + this.log.step("nexe " + version, "info"); + this.bundle = new Bundle(options); if (isWindows) { - const originalPath = process.env.PATH - delete process.env.PATH - this.env = { ...process.env } + const originalPath = process.env.PATH; + delete process.env.PATH; + this.env = { ...process.env }; this.env.PATH = python - ? (this.env.PATH = dequote(normalize(python)) + delimiter + originalPath) - : originalPath - process.env.PATH = originalPath + ? (this.env.PATH = + dequote(normalize(python)) + delimiter + originalPath) + : originalPath; + process.env.PATH = originalPath; } else { - this.env = { ...process.env } - python && (this.env.PYTHON = python) + this.env = { ...process.env }; + python && (this.env.PYTHON = python); } } @bound addResource(absoluteFileName: string, content?: Buffer | string | File) { - return this.bundle.addResource(absoluteFileName, content) + return this.bundle.addResource(absoluteFileName, content); } @bound async readFileAsync(file: string) { - this.assertBuild() - let cachedFile = this.files.find((x) => normalize(x.filename) === normalize(file)) + this.assertBuild(); + let cachedFile = this.files.find( + (x) => normalize(x.filename) === normalize(file) + ); if (!cachedFile) { - const absPath = join(this.src, file) + const absPath = join(this.src, file); cachedFile = { absPath, filename: file, - contents: await readFileAsync(absPath, 'utf-8').catch((x) => { - if (x.code === 'ENOENT') return '' - throw x + contents: await readFileAsync(absPath, "utf-8").catch((x) => { + if (x.code === "ENOENT") return ""; + throw x; }), - } - this.files.push(cachedFile) + }; + this.files.push(cachedFile); } - return cachedFile + return cachedFile; } @bound writeFileAsync(file: string, contents: string | Buffer) { - this.assertBuild() - return writeFileAsync(join(this.src, file), contents) + this.assertBuild(); + return writeFileAsync(join(this.src, file), contents); } @bound - async replaceInFileAsync(file: string, replace: string | RegExp, value: string | StringReplacer) { - const entry = await this.readFileAsync(file) - entry.contents = entry.contents.toString().replace(replace, value as any) + async replaceInFileAsync( + file: string, + replace: string | RegExp, + value: string | StringReplacer + ) { + const entry = await this.readFileAsync(file); + entry.contents = entry.contents.toString().replace(replace, value as any); } @bound async setFileContentsAsync(file: string, contents: string | Buffer) { - const entry = await this.readFileAsync(file) - entry.contents = contents + const entry = await this.readFileAsync(file); + entry.contents = contents; } quit(error?: any) { - const time = Date.now() - this.start - this.log.write(`Finished in ${time / 1000}s`, error ? 'red' : 'green') - return this.log.flush() + const time = Date.now() - this.start; + this.log.write(`Finished in ${time / 1000}s`, error ? "red" : "green"); + return this.log.flush(); } assertBuild() { if (!this.options.build) { - throw new NexeError('This feature is only available with `--build`') + throw new NexeError("This feature is only available with `--build`"); } } public getNodeExecutableLocation(target?: NexeTarget) { if (this.options.asset) { - return resolve(this.options.cwd, this.options.asset) + return resolve(this.options.cwd, this.options.asset); } if (target) { - return join(this.options.temp, target.toString()) + return join(this.options.temp, target.toString()); } - return this.nodeSrcBinPath + return this.nodeSrcBinPath; } private _runBuildCommandAsync(command: string, args: string[]) { if (this.log.verbose) { - this.compileStep!.pause() + this.compileStep!.pause(); } return new Promise((resolve, reject) => { spawn(command, args, { cwd: this.src, env: this.env, shell: true, - stdio: this.log.verbose ? 'inherit' : 'ignore', + stdio: this.log.verbose ? "inherit" : "ignore", }) - .once('error', (e: Error) => { + .once("error", (e: Error) => { if (this.log.verbose) { - this.compileStep!.resume() + this.compileStep!.resume(); } - reject(e) + reject(e); }) - .once('close', (code: number) => { + .once("close", (code: number) => { if (this.log.verbose) { - this.compileStep!.resume() + this.compileStep!.resume(); } if (code != 0) { - const error = `${command} ${args.join(' ')} exited with code: ${code}` - reject(new NexeError(error)) + const error = `${command} ${args.join( + " " + )} exited with code: ${code}`; + reject(new NexeError(error)); } - resolve() - }) - }) + resolve(); + }); + }); } private _configureAsync() { - if (isWindows && semverGt(this.target.version, '10.15.99')) { - return Promise.resolve() + if (isWindows && semverGt(this.target.version, "10.15.99")) { + return Promise.resolve(); } - return this._runBuildCommandAsync(this.env.PYTHON || 'python', [ + return this._runBuildCommandAsync(this.env.PYTHON || "python", [ this.configureScript, ...this.options.configure, - ]) + ]); } public async build(): Promise { this.compileStep!.log( `Configuring node build${ - this.options.configure.length ? ': ' + this.options.configure : '...' + this.options.configure.length ? ": " + this.options.configure : "..." }` - ) - await this._configureAsync() - const buildOptions = this.options.make + ); + await this._configureAsync(); + const buildOptions = this.options.make; this.compileStep!.log( - `Compiling Node${buildOptions.length ? ' with arguments: ' + buildOptions : '...'}` - ) - await this._runBuildCommandAsync(make, buildOptions) - return createReadStream(this.getNodeExecutableLocation()) + `Compiling Node${ + buildOptions.length ? " with arguments: " + buildOptions : "..." + }` + ); + await this._runBuildCommandAsync(make, buildOptions); + return createReadStream(this.getNodeExecutableLocation()); } - private async _shouldCompileBinaryAsync(binary: NodeJS.ReadableStream | null, location: string) { + private async _shouldCompileBinaryAsync( + binary: NodeJS.ReadableStream | null, + location: string + ) { //SOMEDAY combine make/configure/vcBuild/and modified times of included files - const { snapshot, build } = this.options + const { snapshot, build } = this.options; if (!binary) { - return true + return true; } if (build && snapshot != null && (await pathExistsAsync(snapshot))) { - const snapshotLastModified = (await statAsync(snapshot)).mtimeMs - const binaryLastModified = (await statAsync(location)).mtimeMs - return snapshotLastModified > binaryLastModified + const snapshotLastModified = (await statAsync(snapshot)).mtimeMs; + const binaryLastModified = (await statAsync(location)).mtimeMs; + return snapshotLastModified > binaryLastModified; } - return false + return false; } async compileAsync(target: NexeTarget) { - const step = (this.compileStep = this.log.step('Compiling result')) - const build = this.options.build - const location = this.getNodeExecutableLocation(build ? undefined : target) - let binary = (await pathExistsAsync(location)) ? createReadStream(location) : null + const step = (this.compileStep = this.log.step("Compiling result")); + const build = this.options.build; + const location = this.getNodeExecutableLocation(build ? undefined : target); + let binary = (await pathExistsAsync(location)) + ? createReadStream(location) + : null; if (await this._shouldCompileBinaryAsync(binary, location)) { - binary = await this.build() - step.log('Node binary compiled') + binary = await this.build(); + step.log("Node binary compiled"); } - return this._assembleDeliverable(binary!) + return this._assembleDeliverable(binary!); } code() { - return [this.shims.join(''), this.startup].join(';') + return [this.shims.join(""), this.startup].join(";"); } private async _assembleDeliverable(binary: Readable) { if (!this.options.mangle) { - return binary + return binary; } - const launchCode = this.code() - const codeSize = Buffer.byteLength(launchCode) - const sentinel = Buffer.from('') + const launchCode = this.code(); + const codeSize = Buffer.byteLength(launchCode); + const sentinel = Buffer.from(""); - let vfsSize = 0 + let vfsSize = 0; const streams = [ binary, toStream(launchCode), this.bundle.toStream().pipe( new Transform({ transform: (chunk, _, cb) => { - vfsSize || this.bundle.finalize() - chunk && (vfsSize += chunk.length) - cb(null, chunk) + vfsSize || this.bundle.finalize(); + chunk && (vfsSize += chunk.length); + cb(null, chunk); }, }) ), - ] + ]; - let done = false + let done = false; return new MultiStream((cb) => { - if (done) cb(null, null) - else if (streams.length) cb(null, streams.shift() as Readable) + if (done) cb(null, null); + else if (streams.length) cb(null, streams.shift() as Readable); else { - done = true - const trailers = Buffer.alloc(16) - trailers.writeDoubleLE(codeSize, 0) - trailers.writeDoubleLE(vfsSize, 8) - cb(null, toStream(Buffer.concat([sentinel, trailers]))) + done = true; + const trailers = Buffer.alloc(16); + trailers.writeDoubleLE(codeSize, 0); + trailers.writeDoubleLE(vfsSize, 8); + cb(null, toStream(Buffer.concat([sentinel, trailers]))); } - }) + }); } } diff --git a/src/fs/SnapshotZipFS.ts b/src/fs/SnapshotZipFS.ts index 186024c..51206e9 100644 --- a/src/fs/SnapshotZipFS.ts +++ b/src/fs/SnapshotZipFS.ts @@ -1,4 +1,4 @@ -import { Libzip } from '@yarnpkg/libzip' +import { Libzip } from "@yarnpkg/libzip"; import { FakeFS, PortablePath, @@ -13,45 +13,50 @@ import { npath, Filename, CustomDir, -} from '@yarnpkg/fslib' -import { ZipFS, ZipOpenFS } from '@yarnpkg/libzip' -import { resolve, toNamespacedPath } from 'path' -import { constants } from 'fs' +} from "@yarnpkg/fslib"; +import { ZipFS, ZipOpenFS } from "@yarnpkg/libzip"; +import { resolve, toNamespacedPath } from "path"; +import { constants } from "fs"; export type SnapshotZipFSOptions = { - baseFs: FakeFS - libzip: Libzip | (() => Libzip) - zipFs: ZipFS - root: string -} + baseFs: FakeFS; + libzip: Libzip | (() => Libzip); + zipFs: ZipFS; + root: string; +}; -const uniqBy = (arr: Array, pick: (...arg: any[]) => any) => { - const seen = new Set() +const uniqBy = ( + arr: Array>, + pick: (...arg: any[]) => any +) => { + const seen = new Set(); return arr.filter((x) => { - const key = pick(x) - if (seen.has(key)) return false - seen.add(key) - return true - }) -} -function uniqReaddir(arr: Array) { - return uniqBy(arr, (s: string | Dirent) => (typeof s === 'string' ? s : s.name)) + const key = pick(x); + if (seen.has(key)) return false; + seen.add(key); + return true; + }); +}; +function uniqReaddir(arr: Array>) { + return uniqBy(arr, (s: string | Dirent) => + typeof s === "string" ? s : s.name + ); } export class SnapshotZipFS extends BasePortableFakeFS { - zipFs: ZipFS - baseFs: FakeFS - root: string - magic: number + zipFs: ZipFS; + baseFs: FakeFS; + root: string; + magic: number; constructor(opts: SnapshotZipFSOptions) { - super() - this.zipFs = opts.zipFs - this.baseFs = opts.baseFs - this.root = opts.root - this.magic = 0x2a << 24 + super(); + this.zipFs = opts.zipFs; + this.baseFs = opts.baseFs; + this.root = opts.root; + this.magic = 0x2a << 24; } - private readonly fdMap: Map = new Map() - private nextFd = 3 + private readonly fdMap: Map = new Map(); + private nextFd = 3; async makeCallPromise( p: FSPath, @@ -59,38 +64,41 @@ export class SnapshotZipFS extends BasePortableFakeFS { accept: (zipFS: ZipFS, zipInfo: { subPath: PortablePath }) => Promise, { requireSubpath = true }: { requireSubpath?: boolean } = {} ): Promise { - if (typeof p !== 'string') return await discard() + if (typeof p !== "string") return await discard(); - const normalizedP = this.resolve(p) + const normalizedP = this.resolve(p); - const zipInfo = this.findZip(normalizedP) - if (!zipInfo) return await discard() + const zipInfo = this.findZip(normalizedP); + if (!zipInfo) return await discard(); - if (requireSubpath && zipInfo.subPath === '/') return await discard() + if (requireSubpath && zipInfo.subPath === "/") return await discard(); - return await accept(this.zipFs, zipInfo) + return await accept(this.zipFs, zipInfo); } makeCallSync( p: FSPath, discard: () => T, - accept: (zipFS: ZipFS, zipInfo: { subPath: PortablePath; archivePath: string }) => T, + accept: ( + zipFS: ZipFS, + zipInfo: { subPath: PortablePath; archivePath: string } + ) => T, { requireSubpath = true }: { requireSubpath?: boolean } = {} ): T { - if (typeof p !== 'string') return discard() + if (typeof p !== "string") return discard(); - const normalizedP = this.resolve(p) + const normalizedP = this.resolve(p); - const zipInfo = this.findZip(normalizedP) - if (!zipInfo) return discard() + const zipInfo = this.findZip(normalizedP); + if (!zipInfo) return discard(); - if (requireSubpath && zipInfo.subPath === '/') return discard() + if (requireSubpath && zipInfo.subPath === "/") return discard(); - return accept(this.zipFs, { archivePath: '', ...zipInfo }) + return accept(this.zipFs, { archivePath: "", ...zipInfo }); } async realpathPromise(p: PortablePath) { - return await this.realpathSync(p) + return await this.realpathSync(p); } realpathSync(p: PortablePath) { @@ -99,26 +107,29 @@ export class SnapshotZipFS extends BasePortableFakeFS { () => this.baseFs.realpathSync(p), (zipFs, { subPath }) => { if (zipFs.lstatSync(subPath).isSymbolicLink()) { - return zipFs.realpathSync(subPath) + return zipFs.realpathSync(subPath); } else { // return the original path in case it wasn't under /snapshot, e.g. if it was for a node module - otherwise the node module parent path is the wrong one (and other things resolve relative to that) - return p + return p; } } - ) + ); } findZip(p: PortablePath) { - p = this.resolve(p) - const snapshotPP = npath.toPortablePath('/snapshot') + p = this.resolve(p); + const snapshotPP = npath.toPortablePath("/snapshot"); const pathsToTry = Array.from( new Set([ p, - resolve('/snapshot', p), + resolve("/snapshot", p), ppath.resolve( snapshotPP, npath.toPortablePath( - npath.relative(npath.fromPortablePath(this.root), npath.fromPortablePath(p)) + npath.relative( + npath.fromPortablePath(this.root), + npath.fromPortablePath(p) + ) ) ), ppath.resolve( @@ -133,7 +144,10 @@ export class SnapshotZipFS extends BasePortableFakeFS { ppath.resolve( snapshotPP, npath.toPortablePath( - npath.relative(npath.fromPortablePath(process.cwd()), npath.fromPortablePath(p)) + npath.relative( + npath.fromPortablePath(process.cwd()), + npath.fromPortablePath(p) + ) ) ), ppath.resolve( @@ -146,18 +160,18 @@ export class SnapshotZipFS extends BasePortableFakeFS { ) ), ]) - ) + ); for (const path of pathsToTry) { - const portablePath = npath.toPortablePath(path) + const portablePath = npath.toPortablePath(path); if (this.zipFs.existsSync(portablePath)) { return { subPath: portablePath, - } + }; } } } - async copyFilePromise(sourceP: PortablePath, destP: PortablePath, flags: number = 0) { + async copyFilePromise(sourceP: PortablePath, destP: PortablePath, flags = 0) { const fallback = async ( sourceFs: FakeFS, sourceP: PortablePath, @@ -166,40 +180,49 @@ export class SnapshotZipFS extends BasePortableFakeFS { ) => { if ((flags & constants.COPYFILE_FICLONE_FORCE) !== 0) throw Object.assign( - new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), + new Error( + `EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'` + ), { code: `EXDEV` } - ) - if (flags & constants.COPYFILE_EXCL && (await this.existsPromise(sourceP))) + ); + if ( + flags & constants.COPYFILE_EXCL && + (await this.existsPromise(sourceP)) + ) throw Object.assign( - new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), + new Error( + `EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'` + ), { code: `EEXIST` } - ) + ); - let content + let content; try { - content = await sourceFs.readFilePromise(sourceP) + content = await sourceFs.readFilePromise(sourceP); } catch (error) { throw Object.assign( - new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), + new Error( + `EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'` + ), { code: `EINVAL` } - ) + ); } - await destFs.writeFilePromise(destP, content) - } + await destFs.writeFilePromise(destP, content); + }; return await this.makeCallPromise( sourceP, async () => { - return await this.baseFs.copyFilePromise(sourceP, destP, flags) + return await this.baseFs.copyFilePromise(sourceP, destP, flags); }, async (zipFsS, { subPath: subPathS }) => { - return await fallback(zipFsS, subPathS, this.baseFs, destP) + return await fallback(zipFsS, subPathS, this.baseFs, destP); } - ) + ); } - copyFileSync(sourceP: PortablePath, destP: PortablePath, flags: number = 0) { + copyFileSync(sourceP: PortablePath, destP: PortablePath, flags = 0) { const fallback = ( sourceFs: FakeFS, sourceP: PortablePath, @@ -208,203 +231,239 @@ export class SnapshotZipFS extends BasePortableFakeFS { ) => { if ((flags & constants.COPYFILE_FICLONE_FORCE) !== 0) throw Object.assign( - new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), + new Error( + `EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'` + ), { code: `EXDEV` } - ) + ); if (flags & constants.COPYFILE_EXCL && this.existsSync(sourceP)) throw Object.assign( - new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), + new Error( + `EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'` + ), { code: `EEXIST` } - ) + ); - let content + let content; try { - content = sourceFs.readFileSync(sourceP) + content = sourceFs.readFileSync(sourceP); } catch (error) { throw Object.assign( - new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), + new Error( + `EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'` + ), { code: `EINVAL` } - ) + ); } - destFs.writeFileSync(destP, content) - } + destFs.writeFileSync(destP, content); + }; return this.makeCallSync( sourceP, () => { - return this.baseFs.copyFileSync(sourceP, destP, flags) + return this.baseFs.copyFileSync(sourceP, destP, flags); }, (zipFsS, { subPath: subPathS }) => { - return fallback(zipFsS, subPathS, this.baseFs, destP) + return fallback(zipFsS, subPathS, this.baseFs, destP); } - ) + ); } - async readdirPromise(p: PortablePath): Promise> + async readdirPromise(p: PortablePath): Promise>; async readdirPromise( p: PortablePath, opts: { withFileTypes: false } | null - ): Promise> - async readdirPromise(p: PortablePath, opts: { withFileTypes: true }): Promise> + ): Promise>; + async readdirPromise( + p: PortablePath, + opts: { withFileTypes: true } + ): Promise>>; async readdirPromise( p: PortablePath, opts: { withFileTypes: boolean } - ): Promise | Array> + ): Promise | Array>>; async readdirPromise( p: PortablePath, opts?: { withFileTypes?: boolean } | null - ): Promise> { + ): Promise>> { const fallback = async () => { - return await this.baseFs.readdirPromise(p, opts as any) - } + return await this.baseFs.readdirPromise(p, opts as any); + }; return await this.makeCallPromise( p, fallback, async (zipFs, { subPath }) => { - const fallbackPaths: Array = await fallback().catch(() => []) + const fallbackPaths: Array> = + await fallback().catch(() => []); return Promise.resolve( - uniqReaddir(fallbackPaths.concat(await zipFs.readdirPromise(subPath, opts as any))) - ) + uniqReaddir( + fallbackPaths.concat( + await zipFs.readdirPromise(subPath, opts as any) + ) + ) + ); }, { requireSubpath: false, } - ) + ); } - readdirSync(p: PortablePath): Array - readdirSync(p: PortablePath, opts: { withFileTypes: false } | null): Array - readdirSync(p: PortablePath, opts: { withFileTypes: true }): Array - readdirSync(p: PortablePath, opts: { withFileTypes: boolean }): Array | Array - readdirSync(p: PortablePath, opts?: { withFileTypes?: boolean } | null): Array { + readdirSync(p: PortablePath): Array; + readdirSync( + p: PortablePath, + opts: { withFileTypes: false } | null + ): Array; + readdirSync( + p: PortablePath, + opts: { withFileTypes: true } + ): Array>; + readdirSync( + p: PortablePath, + opts: { withFileTypes: boolean } + ): Array | Array>; + readdirSync( + p: PortablePath, + opts?: { withFileTypes?: boolean } | null + ): Array> { const fallback = () => { - return this.baseFs.readdirSync(p, opts as any) - } + return this.baseFs.readdirSync(p, opts as any); + }; return this.makeCallSync( p, fallback, (zipFs, { subPath }) => { - let fallbackPaths: Array = [] + let fallbackPaths: Array> = []; try { - fallbackPaths = fallback() + fallbackPaths = fallback(); } catch (e) {} - return fallbackPaths.concat(uniqReaddir(zipFs.readdirSync(subPath, opts as any))) + return fallbackPaths.concat( + uniqReaddir(zipFs.readdirSync(subPath, opts as any)) + ); }, { requireSubpath: false, } - ) + ); } async mkdirPromise(p: PortablePath, opts?: MkdirOptions) { - return await this.baseFs.mkdirPromise(p, opts) + return await this.baseFs.mkdirPromise(p, opts); } mkdirSync(p: PortablePath, opts?: MkdirOptions) { - return this.baseFs.mkdirSync(p, opts) + return this.baseFs.mkdirSync(p, opts); } async rmdirPromise(p: PortablePath, opts?: RmdirOptions) { - return await this.baseFs.rmdirPromise(p, opts) + return await this.baseFs.rmdirPromise(p, opts); } rmdirSync(p: PortablePath, opts?: RmdirOptions) { - return this.baseFs.rmdirSync(p, opts) + return this.baseFs.rmdirSync(p, opts); + } + + async rmPromise(p: PortablePath, opts?: any) { + return await this.baseFs.rmPromise(p, opts); + } + + rmSync(p: PortablePath, opts?: any) { + return this.baseFs.rmSync(p, opts); } async opendirPromise(p: PortablePath, opts?: OpendirOptions) { - return this.opendirSync(p, opts) + return this.opendirSync(p, opts); } opendirSync(p: PortablePath, opts?: OpendirOptions) { - const zipInfo = this.findZip(p) - let zipFsDir: Dir | null = null + const zipInfo = this.findZip(p); + let zipFsDir: Dir | null = null; if (zipInfo) { - zipFsDir = this.zipFs.opendirSync(zipInfo.subPath) + zipFsDir = this.zipFs.opendirSync(zipInfo.subPath); } - let realFsDir: Dir | null = null + let realFsDir: Dir | null = null; try { - realFsDir = this.baseFs.opendirSync(p) + realFsDir = this.baseFs.opendirSync(p); } catch (e) { - if (!zipFsDir) throw e + if (!zipFsDir) throw e; } - const seen = new Set() + const seen = new Set(); const nextDirent = () => { - const entry = realFsDir?.readSync() || zipFsDir?.readSync() + const entry = realFsDir?.readSync() || zipFsDir?.readSync(); if (entry && !seen.has(entry.name)) { - seen.add(entry.name) - return entry + seen.add(entry.name); + return entry; } - return null - } + return null; + }; const onClose = () => { - zipFsDir?.closeSync() - realFsDir?.closeSync() - } + zipFsDir?.closeSync(); + realFsDir?.closeSync(); + }; - return new CustomDir(p, nextDirent, { onClose }) + return new CustomDir(p, nextDirent, { onClose }); } - accessPromise = ZipOpenFS.prototype.accessPromise - accessSync = ZipOpenFS.prototype.accessSync - appendFilePromise = ZipOpenFS.prototype.appendFilePromise - appendFileSync = ZipOpenFS.prototype.appendFileSync - chmodPromise = ZipOpenFS.prototype.chmodPromise - chmodSync = ZipOpenFS.prototype.chmodSync - fchmodPromise = ZipOpenFS.prototype.fchmodPromise - fchmodSync = ZipOpenFS.prototype.fchmodSync - chownPromise = ZipOpenFS.prototype.chownPromise - chownSync = ZipOpenFS.prototype.chownSync - fchownPromise = ZipOpenFS.prototype.fchownPromise - fchownSync = ZipOpenFS.prototype.fchownSync - closePromise = ZipOpenFS.prototype.closePromise - closeSync = ZipOpenFS.prototype.closeSync - createReadStream = ZipOpenFS.prototype.createReadStream - createWriteStream = ZipOpenFS.prototype.createWriteStream - existsPromise = ZipOpenFS.prototype.existsPromise - existsSync = ZipOpenFS.prototype.existsSync - fstatPromise = ZipOpenFS.prototype.fstatPromise - fstatSync = ZipOpenFS.prototype.fstatSync - getExtractHint = ZipOpenFS.prototype.getExtractHint - getRealPath = ZipOpenFS.prototype.getRealPath - linkPromise = ZipOpenFS.prototype.linkPromise - linkSync = ZipOpenFS.prototype.linkSync - lstatPromise = ZipOpenFS.prototype.lstatPromise - lstatSync = ZipOpenFS.prototype.lstatSync - openPromise = ZipOpenFS.prototype.openPromise - openSync = ZipOpenFS.prototype.openSync - readFilePromise = ZipOpenFS.prototype.readFilePromise - readFileSync = ZipOpenFS.prototype.readFileSync - readlinkPromise = ZipOpenFS.prototype.readlinkPromise - readlinkSync = ZipOpenFS.prototype.readlinkSync - readPromise = ZipOpenFS.prototype.readPromise - readSync = ZipOpenFS.prototype.readSync - renamePromise = ZipOpenFS.prototype.renamePromise - renameSync = ZipOpenFS.prototype.renameSync - resolve = ZipOpenFS.prototype.resolve - statPromise = ZipOpenFS.prototype.statPromise - statSync = ZipOpenFS.prototype.statSync - symlinkPromise = ZipOpenFS.prototype.symlinkPromise - symlinkSync = ZipOpenFS.prototype.symlinkSync - truncatePromise = ZipOpenFS.prototype.truncatePromise - truncateSync = ZipOpenFS.prototype.truncateSync - ftruncatePromise = ZipOpenFS.prototype.ftruncatePromise - ftruncateSync = ZipOpenFS.prototype.ftruncateSync - unlinkPromise = ZipOpenFS.prototype.unlinkPromise - unlinkSync = ZipOpenFS.prototype.unlinkSync - unwatchFile = ZipOpenFS.prototype.unwatchFile - utimesPromise = ZipOpenFS.prototype.utimesPromise - utimesSync = ZipOpenFS.prototype.utimesSync - lutimesPromise = ZipOpenFS.prototype.utimesPromise - lutimesSync = ZipOpenFS.prototype.utimesSync - watch = ZipOpenFS.prototype.watch - watchFile = ZipOpenFS.prototype.watchFile - writeFilePromise = ZipOpenFS.prototype.writeFilePromise - writeFileSync = ZipOpenFS.prototype.writeFileSync - writePromise = ZipOpenFS.prototype.writePromise - writeSync = ZipOpenFS.prototype.writeSync + accessPromise = ZipOpenFS.prototype.accessPromise; + accessSync = ZipOpenFS.prototype.accessSync; + appendFilePromise = ZipOpenFS.prototype.appendFilePromise; + appendFileSync = ZipOpenFS.prototype.appendFileSync; + chmodPromise = ZipOpenFS.prototype.chmodPromise; + chmodSync = ZipOpenFS.prototype.chmodSync; + fchmodPromise = ZipOpenFS.prototype.fchmodPromise; + fchmodSync = ZipOpenFS.prototype.fchmodSync; + chownPromise = ZipOpenFS.prototype.chownPromise; + chownSync = ZipOpenFS.prototype.chownSync; + fchownPromise = ZipOpenFS.prototype.fchownPromise; + fchownSync = ZipOpenFS.prototype.fchownSync; + closePromise = ZipOpenFS.prototype.closePromise; + closeSync = ZipOpenFS.prototype.closeSync; + createReadStream = ZipOpenFS.prototype.createReadStream; + createWriteStream = ZipOpenFS.prototype.createWriteStream; + existsPromise = ZipOpenFS.prototype.existsPromise; + existsSync = ZipOpenFS.prototype.existsSync; + fstatPromise = ZipOpenFS.prototype.fstatPromise; + fstatSync = ZipOpenFS.prototype.fstatSync; + getExtractHint = ZipOpenFS.prototype.getExtractHint; + getRealPath = ZipOpenFS.prototype.getRealPath; + linkPromise = ZipOpenFS.prototype.linkPromise; + linkSync = ZipOpenFS.prototype.linkSync; + lstatPromise = ZipOpenFS.prototype.lstatPromise; + lstatSync = ZipOpenFS.prototype.lstatSync; + openPromise = ZipOpenFS.prototype.openPromise; + openSync = ZipOpenFS.prototype.openSync; + readFilePromise = ZipOpenFS.prototype.readFilePromise; + readFileSync = ZipOpenFS.prototype.readFileSync; + readlinkPromise = ZipOpenFS.prototype.readlinkPromise; + readlinkSync = ZipOpenFS.prototype.readlinkSync; + readPromise = ZipOpenFS.prototype.readPromise; + readSync = ZipOpenFS.prototype.readSync; + renamePromise = ZipOpenFS.prototype.renamePromise; + renameSync = ZipOpenFS.prototype.renameSync; + resolve = ZipOpenFS.prototype.resolve; + statPromise = ZipOpenFS.prototype.statPromise; + statSync = ZipOpenFS.prototype.statSync; + symlinkPromise = ZipOpenFS.prototype.symlinkPromise; + symlinkSync = ZipOpenFS.prototype.symlinkSync; + truncatePromise = ZipOpenFS.prototype.truncatePromise; + truncateSync = ZipOpenFS.prototype.truncateSync; + ftruncatePromise = ZipOpenFS.prototype.ftruncatePromise; + ftruncateSync = ZipOpenFS.prototype.ftruncateSync; + unlinkPromise = ZipOpenFS.prototype.unlinkPromise; + unlinkSync = ZipOpenFS.prototype.unlinkSync; + unwatchFile = ZipOpenFS.prototype.unwatchFile; + utimesPromise = ZipOpenFS.prototype.utimesPromise; + utimesSync = ZipOpenFS.prototype.utimesSync; + lutimesPromise = ZipOpenFS.prototype.utimesPromise; + lutimesSync = ZipOpenFS.prototype.utimesSync; + watch = ZipOpenFS.prototype.watch; + watchFile = ZipOpenFS.prototype.watchFile; + writeFilePromise = ZipOpenFS.prototype.writeFilePromise; + writeFileSync = ZipOpenFS.prototype.writeFileSync; + writePromise = ZipOpenFS.prototype.writePromise; + writeSync = ZipOpenFS.prototype.writeSync; // @ts-ignore - remapFd = ZipOpenFS.prototype.remapFd + remapFd = ZipOpenFS.prototype.remapFd; } diff --git a/src/fs/bundle.ts b/src/fs/bundle.ts index 024b425..37c55ef 100644 --- a/src/fs/bundle.ts +++ b/src/fs/bundle.ts @@ -1,51 +1,54 @@ -import { relative } from 'path' -import { Readable } from 'stream' -import { File } from 'resolve-dependencies' -import archiver from 'archiver' +import { relative } from "path"; +import { Readable } from "stream"; +import { File } from "resolve-dependencies"; +import archiver from "archiver"; function makeRelativeToZip(cwd: string, path: string) { - return '/snapshot/' + relative(cwd, path) + return "/snapshot/" + relative(cwd, path); } export function toStream(content: Buffer | string) { const readable = new Readable({ read() { - this.push(content) - this.push(null) + this.push(content); + this.push(null); }, - }) - return readable + }); + return readable; } export class Bundle { - cwd: string - files = new Set() - zip: any + cwd: string; + files = new Set(); + zip: any; constructor({ cwd }: { cwd: string } = { cwd: process.cwd() }) { - this.cwd = cwd - this.zip = archiver('zip') + this.cwd = cwd; + this.zip = archiver("zip"); } get list() { - return Array.from(this.files) + return Array.from(this.files); } - public addResource(absoluteFileName: string, content?: File | Buffer | string) { - const destPath = makeRelativeToZip(this.cwd, absoluteFileName) + public addResource( + absoluteFileName: string, + content?: File | Buffer | string + ) { + const destPath = makeRelativeToZip(this.cwd, absoluteFileName); if (!this.files.has(destPath)) { if (content == null) { - this.zip.file(absoluteFileName, { name: destPath }) + this.zip.file(absoluteFileName, { name: destPath }); } else { - this.zip.append(content, { name: destPath }) + this.zip.append(content, { name: destPath }); } - this.files.add(destPath) + this.files.add(destPath); } } public finalize() { - return this.zip.finalize() + return this.zip.finalize(); } public toStream(): Readable { - return this.zip + return this.zip; } } diff --git a/src/fs/patch.ts b/src/fs/patch.ts index b345c0c..70e699a 100644 --- a/src/fs/patch.ts +++ b/src/fs/patch.ts @@ -1,117 +1,136 @@ -import { ZipFS, getLibzipSync } from '@yarnpkg/libzip' -import { patchFs, npath, PosixFS, NodeFS } from '@yarnpkg/fslib' -import { SnapshotZipFS } from './SnapshotZipFS' -import * as assert from 'assert' -import * as constants from 'constants' -import { dirname } from 'path' +import { ZipFS, getLibzipSync } from "@yarnpkg/libzip"; +import { patchFs, npath, PosixFS, NodeFS } from "@yarnpkg/fslib"; +import { SnapshotZipFS } from "./SnapshotZipFS"; +import * as assert from "assert"; +import * as constants from "constants"; +import { dirname } from "path"; export interface NexeHeader { - blobPath: string + blobPath: string; layout: { - resourceStart: number - resourceSize: number - contentSize: number - contentStart: number - } + resourceStart: number; + resourceSize: number; + contentSize: number; + contentStart: number; + }; } -let originalFsMethods: any = null -let lazyRestoreFs = () => {} -const patches = (process as any).nexe.patches || {} -const originalPatches = { ...patches } -delete (process as any).nexe +let originalFsMethods: any = null; +let lazyRestoreFs = () => {}; +const patches = (process as any).nexe.patches || {}; +const originalPatches = { ...patches }; +delete (process as any).nexe; -function shimFs(binary: NexeHeader, fs: typeof import('fs') = require('fs')) { +function shimFs(binary: NexeHeader, fs: typeof import("fs") = require("fs")) { if (originalFsMethods !== null) { - return + return; } - originalFsMethods = Object.assign({}, fs) + originalFsMethods = Object.assign({}, fs); - const realFs: typeof fs = { ...fs } - const nodeFs = new NodeFS(realFs) + const realFs: typeof fs = { ...fs }; + const nodeFs = new NodeFS(realFs); - const blob = Buffer.allocUnsafe(binary.layout.resourceSize) - const blobFd = realFs.openSync(binary.blobPath, 'r') + const blob = Buffer.allocUnsafe(binary.layout.resourceSize); + const blobFd = realFs.openSync(binary.blobPath, "r"); const bytesRead = realFs.readSync( blobFd, blob, 0, binary.layout.resourceSize, binary.layout.resourceStart - ) - assert.equal(bytesRead, binary.layout.resourceSize) + ); + assert.equal(bytesRead, binary.layout.resourceSize); - const zipFs = new ZipFS(blob, { readOnly: true }) + const zipFs = new ZipFS(blob, { readOnly: true }); const snapshotZipFS = new SnapshotZipFS({ libzip: getLibzipSync(), zipFs, baseFs: nodeFs, root: dirname(process.argv[0]), - }) - const posixSnapshotZipFs = new PosixFS(snapshotZipFS) - patchFs(fs, posixSnapshotZipFs) + }); + const posixSnapshotZipFs = new PosixFS(snapshotZipFS); + patchFs(fs, posixSnapshotZipFs); - let log = (_: string) => true - if ((process.env.DEBUG || '').toLowerCase().includes('nexe:require')) { + let log = (_: string) => true; + if ((process.env.DEBUG || "").toLowerCase().includes("nexe:require")) { process.stderr.write( // @ts-ignore - `[nexe] - FILES ${JSON.stringify(Array.from(zipFs.entries.keys()), null, 4)}\n` - ) + `[nexe] - FILES ${JSON.stringify( + // @ts-ignore - accessing private property for debugging + Array.from(zipFs.entries.keys()), + null, + 4 + )}\n` + ); process.stderr.write( // @ts-ignore - `[nexe] - DIRECTORIES ${JSON.stringify(Array.from(zipFs.listings.keys()), null, 4)}\n` - ) + `[nexe] - DIRECTORIES ${JSON.stringify( + // @ts-ignore - accessing private property for debugging + Array.from(zipFs.listings.keys()), + null, + 4 + )}\n` + ); log = (text: string) => { - return process.stderr.write(`[nexe] - ${text}\n`) - } + return process.stderr.write(`[nexe] - ${text}\n`); + }; } function internalModuleReadFile(this: any, original: any, ...args: any[]) { - log(`internalModuleReadFile ${args[0]}`) + log(`internalModuleReadFile ${args[0]}`); try { - return posixSnapshotZipFs.readFileSync(args[0], 'utf-8') + return posixSnapshotZipFs.readFileSync(args[0], "utf-8"); } catch (e) { - return '' + return ""; } } if (patches.internalModuleReadFile) { - patches.internalModuleReadFile = internalModuleReadFile + patches.internalModuleReadFile = internalModuleReadFile; } - let returningArray: boolean - patches.internalModuleReadJSON = function (this: any, original: any, ...args: any[]) { - if (returningArray == null) returningArray = Array.isArray(original.call(this, '')) - const res = internalModuleReadFile.call(this, original, ...args) + let returningArray: boolean; + patches.internalModuleReadJSON = function ( + this: any, + original: any, + ...args: any[] + ) { + if (returningArray == null) + returningArray = Array.isArray(original.call(this, "")); + const res = internalModuleReadFile.call(this, original, ...args); return returningArray && !Array.isArray(res) - ? res === '' + ? res === "" ? [] : [res, /"(main|name|type|exports|imports)"/.test(res)] - : res - } - patches.internalModuleStat = function (this: any, original: any, ...args: any[]) { - let statPath = args[0] + : res; + }; + patches.internalModuleStat = function ( + this: any, + original: any, + ...args: any[] + ) { + let statPath = args[0]; //in node 22, the path arg moved to arg[1] - if (typeof args[0] !== 'string') statPath = args[1] - let result = 0 + if (typeof args[0] !== "string") statPath = args[1]; + let result = 0; try { - const stat = posixSnapshotZipFs.statSync(statPath) - if (stat.isDirectory()) result = 1 - else result = 0 + const stat = posixSnapshotZipFs.statSync(statPath); + if (stat.isDirectory()) result = 1; + else result = 0; } catch (e) { - result = -constants.ENOENT + result = -constants.ENOENT; } - log(`internalModuleStat ${result} ${statPath}`) - return result - } + log(`internalModuleStat ${result} ${statPath}`); + return result; + }; lazyRestoreFs = () => { - Object.assign(fs, originalFsMethods) - Object.assign(patches, originalPatches) - lazyRestoreFs = () => {} - } + Object.assign(fs, originalFsMethods); + Object.assign(patches, originalPatches); + lazyRestoreFs = () => {}; + }; } function restoreFs() { - lazyRestoreFs() + lazyRestoreFs(); } -export { shimFs, restoreFs } +export { shimFs, restoreFs }; diff --git a/src/logger.ts b/src/logger.ts index f97bbfd..c8418dd 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,65 +1,65 @@ -import colors from 'chalk' -import ora from 'ora' +import colors from "chalk"; +import ora from "ora"; -const frameLength = 120 +const frameLength = 120; export interface LogStep { - modify(text: string, color?: string): void - log(text: string, color?: string): void - pause(): void - resume(): void + modify(text: string, color?: string): void; + log(text: string, color?: string): void; + pause(): void; + resume(): void; } export class Logger { - public verbose: boolean - private silent: boolean - private ora: any - private modify: Function - public write: (text: string, color?: string) => void + public verbose: boolean; + private silent: boolean; + private ora: any; + private modify: Function; + public write: (text: string, color?: string) => void; - constructor(level: 'verbose' | 'silent' | 'info') { - this.verbose = level === 'verbose' - this.silent = level === 'silent' + constructor(level: "verbose" | "silent" | "info") { + this.verbose = level === "verbose"; + this.silent = level === "silent"; if (!this.silent) { this.ora = ora({ - text: 'Starting...', - color: 'blue', - spinner: 'dots', - }) - this.ora.stop() + text: "Starting...", + color: "blue", + spinner: "dots", + }); + this.ora.stop(); } - const noop = () => {} - this.modify = this.silent ? noop : this._modify.bind(this) - this.write = this.silent ? noop : this._write.bind(this) + const noop = () => {}; + this.modify = this.silent ? noop : this._modify.bind(this); + this.write = this.silent ? noop : this._write.bind(this); } flush() { - !this.silent && this.ora.succeed() - return new Promise((resolve) => setTimeout(resolve, frameLength)) + !this.silent && this.ora.succeed(); + return new Promise((resolve) => setTimeout(resolve, frameLength)); } - _write(update: string, color = 'green') { - this.ora.succeed().text = (colors as any)[color](update) - this.ora.start() + _write(update: string, color = "green") { + this.ora.succeed().text = (colors as any)[color](update); + this.ora.start(); } _modify(update: string, color = this.ora.color) { - this.ora.text = update - this.ora.color = color + this.ora.text = update; + this.ora.color = color; } - step(text: string, method: string = 'succeed'): LogStep { + step(text: string, method = "succeed"): LogStep { if (this.silent) { - return { modify() {}, log() {}, pause() {}, resume() {} } + return { modify() {}, log() {}, pause() {}, resume() {} }; } if (!this.ora.id) { - this.ora.start().text = text - if (method !== 'succeed') { - this.ora[method]() + this.ora.start().text = text; + if (method !== "succeed") { + this.ora[method](); } } else { - this.ora[method]().text = text - this.ora.start() + this.ora[method]().text = text; + this.ora.start(); } return { @@ -67,6 +67,6 @@ export class Logger { log: this.verbose ? this.write : this.modify, pause: () => this.ora.stopAndPersist(), resume: () => this.ora.start(), - } as LogStep + } as LogStep; } } diff --git a/src/nexe.ts b/src/nexe.ts index e15b495..9f81d62 100644 --- a/src/nexe.ts +++ b/src/nexe.ts @@ -1,15 +1,15 @@ -import { EOL } from 'os' -import { compose } from 'app-builder' -import { NexeCompiler, NexeError } from './compiler' -import { normalizeOptions, NexeOptions, NexePatch } from './options' -import resource from './steps/resource' -import clean from './steps/clean' -import cli from './steps/cli' -import bundle from './steps/bundle' -import download from './steps/download' -import shim from './steps/shim' -import artifacts from './steps/artifacts' -import patches from './patches' +import { EOL } from "os"; +import { compose } from "app-builder"; +import { NexeCompiler, NexeError } from "./compiler"; +import { normalizeOptions, NexeOptions, NexePatch } from "./options"; +import resource from "./steps/resource"; +import clean from "./steps/clean"; +import cli from "./steps/cli"; +import bundle from "./steps/bundle"; +import download from "./steps/download"; +import shim from "./steps/shim"; +import artifacts from "./steps/artifacts"; +import patches from "./patches"; async function compile( compilerOptions?: Partial, @@ -17,11 +17,11 @@ async function compile( ) { let error: Error | null = null, options: NexeOptions | null = null, - compiler: NexeCompiler | null = null + compiler: NexeCompiler | null = null; try { - options = normalizeOptions(compilerOptions) - compiler = new NexeCompiler(options) + options = normalizeOptions(compilerOptions); + compiler = new NexeCompiler(options); await compose( clean, resource, @@ -29,21 +29,23 @@ async function compile( bundle, shim, download, - options.build ? [artifacts, ...patches, ...(options.patches as NexePatch[])] : [], + options.build + ? [artifacts, ...patches, ...(options.patches as NexePatch[])] + : [], options.plugins as NexePatch[] - )(compiler) + )(compiler); } catch (e: any) { - error = e + error = e; } if (error) { - compiler && compiler.quit(error) - if (callback) return callback(error) - return Promise.reject(error) + compiler && compiler.quit(error); + if (callback) return callback(error); + return Promise.reject(error); } - if (callback) callback(null) + if (callback) callback(null); } -export { compile, NexeCompiler } -export { argv, version, NexeOptions, help } from './options' +export { compile, NexeCompiler }; +export { argv, version, NexeOptions, help } from "./options"; diff --git a/src/options.ts b/src/options.ts index 230dbb2..ef067dd 100644 --- a/src/options.ts +++ b/src/options.ts @@ -1,61 +1,62 @@ -import parseArgv from 'minimist' -import { NexeCompiler, NexeError } from './compiler' -import { isWindows, STDIN_FLAG } from './util' -import { basename, extname, join, isAbsolute, resolve } from 'path' -import { getTarget, NexeTarget } from './target' -import { EOL, homedir } from 'os' -import chalk from 'chalk' -import { resolveSync } from 'resolve-dependencies' -const caw = require('caw') -const c = process.platform === 'win32' ? chalk.constructor({ enabled: false }) : chalk +import parseArgv from "minimist"; +import { NexeCompiler, NexeError } from "./compiler"; +import { isWindows, STDIN_FLAG } from "./util"; +import { basename, extname, join, isAbsolute, resolve } from "path"; +import { getTarget, NexeTarget } from "./target"; +import { EOL, homedir } from "os"; +import chalk from "chalk"; +import { resolveSync } from "resolve-dependencies"; +const caw = require("caw"); +const c = + process.platform === "win32" ? chalk.constructor({ enabled: false }) : chalk; -export const version = '{{ version }}' +export const version = "{{ version }}"; export interface NexePatch { - (compiler: NexeCompiler, next: () => Promise): Promise + (compiler: NexeCompiler, next: () => Promise): Promise; } export interface NexeOptions { - build: boolean - input: string - output: string - targets: (string | NexeTarget)[] - name: string - remote: string - asset: string - cwd: string - fs: boolean | string[] - flags: string[] - configure: string[] - vcBuild: string[] - make: string[] - snapshot?: string - resources: string[] - temp: string - rc: { [key: string]: string } - enableNodeCli: boolean - bundle: boolean | string - patches: (string | NexePatch)[] - plugins: (string | NexePatch)[] - native: any - mangle: boolean - ghToken: string - sourceUrl?: string - enableStdIn?: boolean - python?: string - loglevel: 'info' | 'silent' | 'verbose' - silent?: boolean - fakeArgv?: boolean - verbose?: boolean - info?: boolean - ico?: string - debugBundle?: boolean - warmup?: string - clean?: boolean + build: boolean; + input: string; + output: string; + targets: (string | NexeTarget)[]; + name: string; + remote: string; + asset: string; + cwd: string; + fs: boolean | string[]; + flags: string[]; + configure: string[]; + vcBuild: string[]; + make: string[]; + snapshot?: string; + resources: string[]; + temp: string; + rc: { [key: string]: string }; + enableNodeCli: boolean; + bundle: boolean | string; + patches: (string | NexePatch)[]; + plugins: (string | NexePatch)[]; + native: any; + mangle: boolean; + ghToken: string; + sourceUrl?: string; + enableStdIn?: boolean; + python?: string; + loglevel: "info" | "silent" | "verbose"; + silent?: boolean; + fakeArgv?: boolean; + verbose?: boolean; + info?: boolean; + ico?: string; + debugBundle?: boolean; + warmup?: string; + clean?: boolean; /** * Api Only */ - downloadOptions: any + downloadOptions: any; } const defaults = { @@ -66,37 +67,37 @@ const defaults = { mangle: true, make: [], targets: [], - vcBuild: isWindows ? ['nosign', 'release'] : [], + vcBuild: isWindows ? ["nosign", "release"] : [], enableNodeCli: false, build: false, bundle: true, patches: [], plugins: [], - remote: 'https://github.com/nexe/nexe/releases/download/v3.3.3/', -} + remote: "https://github.com/nexe/nexe/releases/download/v3.3.3/", +}; const alias = { - i: 'input', - o: 'output', - v: 'version', - a: 'asset', - t: 'target', - b: 'build', - n: 'name', - r: 'resource', - p: 'python', - f: 'flag', - c: 'configure', - m: 'make', - h: 'help', - l: 'loglevel', - 'fake-argv': 'fakeArgv', - 'gh-token': 'ghToken', -} -const argv = parseArgv(process.argv, { alias, default: { ...defaults } }) + i: "input", + o: "output", + v: "version", + a: "asset", + t: "target", + b: "build", + n: "name", + r: "resource", + p: "python", + f: "flag", + c: "configure", + m: "make", + h: "help", + l: "loglevel", + "fake-argv": "fakeArgv", + "gh-token": "ghToken", +}; +const argv = parseArgv(process.argv, { alias, default: { ...defaults } }); let help = ` -${c.bold('nexe [options]')} +${c.bold("nexe [options]")} - ${c.underline.bold('Options:')} + ${c.underline.bold("Options:")} -i --input -- application entry point -o --output -- path to output file @@ -106,7 +107,7 @@ ${c.bold('nexe [options]')} --remote -- alternate location (URL) to download pre-built base (nexe) binaries from --plugin -- extend nexe runtime behavior - ${c.underline.bold('Building from source:')} + ${c.underline.bold("Building from source:")} -b --build -- build from source -p --python -- python3 (as python) executable path @@ -121,7 +122,7 @@ ${c.bold('nexe [options]')} --sourceUrl -- pass an alternate source (node.tar.gz) url --enableNodeCli -- enable node cli enforcement (blocks app cli) - ${c.underline.bold('Other options:')} + ${c.underline.bold("Other options:")} --bundle -- custom bundling module with 'createBundle' export --temp -- temp file storage default '~/.nexe' @@ -131,11 +132,11 @@ ${c.bold('nexe [options]')} --silent -- disable logging --verbose -- set logging to verbose - -* variable key name * option can be used more than once`.trim() -help = EOL + help + EOL + -* variable key name * option can be used more than once`.trim(); +help = EOL + help + EOL; function flatten(...args: any[]): string[] { - return ([] as string[]).concat(...args).filter((x) => x) + return ([] as string[]).concat(...args).filter((x) => x); } /** @@ -148,48 +149,48 @@ function extractCliMap(match: RegExp, options: any) { return Object.keys(options) .filter((x) => match.test(x)) .reduce((map: any, option: any) => { - const key = option.split('-')[1] - map[key] = options[option] - delete options[option] - return map - }, {} as any) + const key = option.split("-")[1]; + map[key] = options[option]; + delete options[option]; + return map; + }, {} as any); } function extractLogLevel(options: NexeOptions) { - if (options.loglevel) return options.loglevel - if (options.silent) return 'silent' - if (options.verbose) return 'verbose' - return 'info' + if (options.loglevel) return options.loglevel; + if (options.silent) return "silent"; + if (options.verbose) return "verbose"; + return "info"; } function isName(name: string) { - return name && name !== 'index' && name !== STDIN_FLAG + return name && name !== "index" && name !== STDIN_FLAG; } function extractName(options: NexeOptions) { - let name = options.name + let name = options.name; //try and use the input filename as the output filename if its not index - if (!isName(name) && typeof options.input === 'string') { - name = basename(options.input).replace(extname(options.input), '') + if (!isName(name) && typeof options.input === "string") { + name = basename(options.input).replace(extname(options.input), ""); } //try and use the directory as the filename if (!isName(name) && basename(options.cwd)) { - name = basename(options.cwd) + name = basename(options.cwd); } - return name.replace(/\.exe$/, '') + return name.replace(/\.exe$/, ""); } function padRelative(input: string) { - let prefix = '' - if (!input.startsWith('.')) { - prefix = './' + let prefix = ""; + if (!input.startsWith(".")) { + prefix = "./"; } - return prefix + input + return prefix + input; } function isEntryFile(filename?: string): filename is string { - return Boolean(filename && !isAbsolute(filename)) + return Boolean(filename && !isAbsolute(filename)); } export function resolveEntry( @@ -198,109 +199,117 @@ export function resolveEntry( maybeEntry: string | undefined, bundle: boolean | string ) { - let result = null - if (input === '-' || maybeEntry === '-') { - return STDIN_FLAG + let result = null; + if (input === "-" || maybeEntry === "-") { + return STDIN_FLAG; } if (input && isAbsolute(input)) { - return input + return input; } if (input) { - const inputPath = padRelative(input) - result = resolveSync(cwd, inputPath) + const inputPath = padRelative(input); + result = resolveSync(cwd, inputPath); } if (isEntryFile(maybeEntry) && (!result || !result.absPath)) { - const inputPath = padRelative(maybeEntry) - result = resolveSync(cwd, inputPath) + const inputPath = padRelative(maybeEntry); + result = resolveSync(cwd, inputPath); } - if (!process.stdin.isTTY && (!result || !result.absPath) && bundle === defaults.bundle) { - return STDIN_FLAG + if ( + !process.stdin.isTTY && + (!result || !result.absPath) && + bundle === defaults.bundle + ) { + return STDIN_FLAG; } if (!result || !result.absPath) { - result = resolveSync(cwd, '.') + result = resolveSync(cwd, "."); } if (!result.absPath) { - throw new NexeError(`Entry file "${input || ''}" not found!`) + throw new NexeError(`Entry file "${input || ""}" not found!`); } - return result.absPath + return result.absPath; } function isCli(options?: Partial) { - return argv === options + return argv === options; } function normalizeOptions(input?: Partial): NexeOptions { - const options = Object.assign({}, defaults, input) as NexeOptions - const opts = options as any - const cwd = (options.cwd = resolve(options.cwd)) + const options = Object.assign({}, defaults, input) as NexeOptions; + const opts = options as any; + const cwd = (options.cwd = resolve(options.cwd)); options.temp = options.temp ? resolve(cwd, options.temp) - : process.env.NEXE_TEMP || join(homedir(), '.nexe') - const maybeEntry = isCli(input) ? argv._[argv._.length - 1] : undefined - options.input = resolveEntry(options.input, cwd, maybeEntry, options.bundle) - options.enableStdIn = isCli(input) && options.input === STDIN_FLAG - options.name = extractName(options) - options.loglevel = extractLogLevel(options) - options.flags = flatten(opts.flag, options.flags) - options.targets = flatten(opts.target, options.targets).map(getTarget) + : process.env.NEXE_TEMP || join(homedir(), ".nexe"); + const maybeEntry = isCli(input) ? argv._[argv._.length - 1] : undefined; + options.input = resolveEntry(options.input, cwd, maybeEntry, options.bundle); + options.enableStdIn = isCli(input) && options.input === STDIN_FLAG; + options.name = extractName(options); + options.loglevel = extractLogLevel(options); + options.flags = flatten(opts.flag, options.flags); + options.targets = flatten(opts.target, options.targets).map(getTarget); if (!options.targets.length) { - options.targets.push(getTarget()) + options.targets.push(getTarget()); } - options.ghToken = options.ghToken || process.env.GITHUB_TOKEN || '' - options.make = flatten(isWindows ? options.vcBuild : options.make) - options.configure = flatten(options.configure) - options.resources = flatten(opts.resource, options.resources) + options.ghToken = options.ghToken || process.env.GITHUB_TOKEN || ""; + options.make = flatten(isWindows ? options.vcBuild : options.make); + options.configure = flatten(options.configure); + options.resources = flatten(opts.resource, options.resources); - if (!options.remote.endsWith('/')) { - options.remote += '/' + if (!options.remote.endsWith("/")) { + options.remote += "/"; } - options.downloadOptions = options.downloadOptions || {} - options.downloadOptions.headers = options.downloadOptions.headers || {} - options.downloadOptions.headers['User-Agent'] = 'nexe (https://www.npmjs.com/package/nexe)' + options.downloadOptions = options.downloadOptions || {}; + options.downloadOptions.headers = options.downloadOptions.headers || {}; + options.downloadOptions.headers["User-Agent"] = + "nexe (https://www.npmjs.com/package/nexe)"; options.downloadOptions.agent = process.env.HTTPS_PROXY - ? caw(process.env.HTTPS_PROXY, { protocol: 'https' }) - : options.downloadOptions.agent || require('https').globalAgent - options.downloadOptions.rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED + ? caw(process.env.HTTPS_PROXY, { protocol: "https" }) + : options.downloadOptions.agent || require("https").globalAgent; + options.downloadOptions.rejectUnauthorized = process.env + .NODE_TLS_REJECT_UNAUTHORIZED ? false - : true + : true; - options.rc = options.rc || extractCliMap(/^rc-.*/, options) + options.rc = options.rc || extractCliMap(/^rc-.*/, options); options.output = - (options.targets[0] as NexeTarget).platform === 'windows' - ? `${(options.output || options.name).replace(/\.exe$/, '')}.exe` - : `${options.output || options.name}` - options.output = resolve(cwd, options.output) + (options.targets[0] as NexeTarget).platform === "windows" + ? `${(options.output || options.name).replace(/\.exe$/, "")}.exe` + : `${options.output || options.name}`; + options.output = resolve(cwd, options.output); const requireDefault = (x: string) => { - if (typeof x === 'string') { - return require(x).default + if (typeof x === "string") { + return require(x).default; } - return x - } + return x; + }; - options.mangle = 'mangle' in opts ? opts.mangle : true - options.plugins = flatten(opts.plugin, options.plugins).map(requireDefault) - options.patches = flatten(opts.patch, options.patches).map(requireDefault) + options.mangle = "mangle" in opts ? opts.mangle : true; + options.plugins = flatten(opts.plugin, options.plugins).map(requireDefault); + options.patches = flatten(opts.patch, options.patches).map(requireDefault); if ((!options.mangle && !options.bundle) || options.patches.length) { - options.build = true + options.build = true; } if (options.build) { - const { arch } = options.targets[0] as NexeTarget + const { arch } = options.targets[0] as NexeTarget; if (isWindows) { - options.make = Array.from(new Set(options.make.concat(arch))) + options.make = Array.from(new Set(options.make.concat(arch))); } else { - options.configure = Array.from(new Set(options.configure.concat([`--dest-cpu=${arch}`]))) + options.configure = Array.from( + new Set(options.configure.concat([`--dest-cpu=${arch}`])) + ); } } Object.keys(alias) - .filter((k) => k !== 'rc') - .forEach((x) => delete opts[x]) + .filter((k) => k !== "rc") + .forEach((x) => delete opts[x]); - return options + return options; } -export { argv, normalizeOptions, help } +export { argv, normalizeOptions, help }; diff --git a/src/patches/boot-nexe.ts b/src/patches/boot-nexe.ts index d983e15..bc39803 100644 --- a/src/patches/boot-nexe.ts +++ b/src/patches/boot-nexe.ts @@ -1,56 +1,57 @@ -const fs = require('fs'), - fd = fs.openSync(process.execPath, 'r'), +const fs = require("fs"), + fd = fs.openSync(process.execPath, "r"), stat = fs.statSync(fd), tailSize = Math.min(stat.size, 16000), tailWindow = Buffer.alloc(tailSize), - match = '', + match = "", matchLength = match.length, - lastBuffer = Buffer.alloc(matchLength + 32) + lastBuffer = Buffer.alloc(matchLength + 32); let offset = stat.size, footerPosition = -1, footerPositionOffset = 0, - footer: Buffer + footer: Buffer; while (true) { - const bytesRead = fs.readSync(fd, tailWindow, 0, tailSize, offset - tailSize) - if (bytesRead === 0) break + const bytesRead = fs.readSync(fd, tailWindow, 0, tailSize, offset - tailSize); + if (bytesRead === 0) break; - const combinedBuffers = Buffer.concat([tailWindow, lastBuffer]) - footerPosition = combinedBuffers.indexOf(match) + const combinedBuffers = Buffer.concat([tailWindow, lastBuffer]); + footerPosition = combinedBuffers.indexOf(match); if (footerPosition > -1) { - footer = combinedBuffers.slice(footerPosition, footerPosition + 32) - break + footer = combinedBuffers.slice(footerPosition, footerPosition + 32); + break; } - if (offset < 0) break + if (offset < 0) break; - tailWindow.copy(lastBuffer) - offset = offset - bytesRead + tailWindow.copy(lastBuffer); + offset = offset - bytesRead; } if (footerPosition == -1) { - throw 'Invalid Nexe binary' + throw "Invalid Nexe binary"; } const contentSize = footer!.readDoubleLE(16), resourceSize = footer!.readDoubleLE(24), - contentStart = offset - tailSize + footerPosition - resourceSize - contentSize, - resourceStart = contentStart + contentSize + contentStart = + offset - tailSize + footerPosition - resourceSize - contentSize, + resourceStart = contentStart + contentSize; Object.defineProperty( process, - '__nexe', + "__nexe", (function () { - let nexeHeader: any = null + let nexeHeader: any = null; return { get: function () { - return nexeHeader + return nexeHeader; }, set: function (value: any) { if (nexeHeader) { - throw new Error('This property is readonly') + throw new Error("This property is readonly"); } nexeHeader = Object.assign({}, value, { blobPath: process.execPath, @@ -61,19 +62,22 @@ Object.defineProperty( resourceSize, resourceStart, }, - }) - Object.freeze(nexeHeader) + }); + Object.freeze(nexeHeader); }, enumerable: false, configurable: false, - } + }; })() -) +); const contentBuffer = Buffer.alloc(contentSize), - Module = require('module') + Module = require("module"); -fs.readSync(fd, contentBuffer, 0, contentSize, contentStart) -fs.closeSync(fd) +fs.readSync(fd, contentBuffer, 0, contentSize, contentStart); +fs.closeSync(fd); -new Module(process.execPath, null)._compile(contentBuffer.slice(1).toString(), process.execPath) +new Module(process.execPath, null)._compile( + contentBuffer.slice(1).toString(), + process.execPath +); diff --git a/src/patches/build-fixes.ts b/src/patches/build-fixes.ts index 217dfc1..b2a72cc 100644 --- a/src/patches/build-fixes.ts +++ b/src/patches/build-fixes.ts @@ -1,17 +1,20 @@ -import { NexeCompiler } from '../compiler' +import { NexeCompiler } from "../compiler"; -export default async function buildFixes(compiler: NexeCompiler, next: () => Promise) { - if (!compiler.target.version.startsWith('8.2')) { - return next() +export default async function buildFixes( + compiler: NexeCompiler, + next: () => Promise +) { + if (!compiler.target.version.startsWith("8.2")) { + return next(); } - const file = await compiler.readFileAsync('./tools/msvs/find_python.cmd') + const file = await compiler.readFileAsync("./tools/msvs/find_python.cmd"); await compiler.replaceInFileAsync( - './tools/msvs/find_python.cmd', - '%p%python.exe -V 2>&1', + "./tools/msvs/find_python.cmd", + "%p%python.exe -V 2>&1", '"%p%python.exe" -V 2>&1' - ) + ); - return next() + return next(); } diff --git a/src/patches/disable-node-cli.ts b/src/patches/disable-node-cli.ts index e7da7bc..65fd04c 100644 --- a/src/patches/disable-node-cli.ts +++ b/src/patches/disable-node-cli.ts @@ -1,50 +1,61 @@ -import { NexeCompiler } from '../compiler' -import { semverGt } from '../util' +import { NexeCompiler } from "../compiler"; +import { semverGt } from "../util"; -export default async function disableNodeCli(compiler: NexeCompiler, next: () => Promise) { +export default async function disableNodeCli( + compiler: NexeCompiler, + next: () => Promise +) { if (compiler.options.enableNodeCli) { - return next() + return next(); } - if (semverGt(compiler.target.version, '18.99')) { + if (semverGt(compiler.target.version, "18.99")) { await compiler.replaceInFileAsync( - 'src/node.cc', + "src/node.cc", /(? 1/g, (match) => { - if (matches++) { - return 'false' + "src/node.cc", + /(? 1/g, + (match) => { + if (matches++) { + return "false"; + } + return match; } - return match - }) + ); } else { - const nodeccMarker = 'argv[index][0] ==' + const nodeccMarker = "argv[index][0] =="; await compiler.replaceInFileAsync( - 'src/node.cc', + "src/node.cc", `${nodeccMarker} '-'`, // allow NODE_OPTIONS, introduced in 8.0 - semverGt(compiler.target.version, '7.99') + semverGt(compiler.target.version, "7.99") ? `(${nodeccMarker} (is_env ? '-' : ']'))` : `(${nodeccMarker} ']')` - ) + ); } - return next() + return next(); } diff --git a/src/patches/flags.ts b/src/patches/flags.ts index 931a4a1..2a171df 100644 --- a/src/patches/flags.ts +++ b/src/patches/flags.ts @@ -1,16 +1,19 @@ -import { NexeCompiler } from '../compiler' +import { NexeCompiler } from "../compiler"; -export default async function flags(compiler: NexeCompiler, next: () => Promise) { - const nodeflags = compiler.options.flags +export default async function flags( + compiler: NexeCompiler, + next: () => Promise +) { + const nodeflags = compiler.options.flags; if (!nodeflags.length) { - return next() + return next(); } await compiler.replaceInFileAsync( - 'node.gyp', + "node.gyp", "'node_v8_options%': ''", - `'node_v8_options%': '${nodeflags.join(' ')}'` - ) + `'node_v8_options%': '${nodeflags.join(" ")}'` + ); - return next() + return next(); } diff --git a/src/patches/gyp.ts b/src/patches/gyp.ts index c050a2a..fe39950 100644 --- a/src/patches/gyp.ts +++ b/src/patches/gyp.ts @@ -1,21 +1,21 @@ -import { NexeCompiler } from '../compiler' +import { NexeCompiler } from "../compiler"; export default async function nodeGyp( { files, replaceInFileAsync }: NexeCompiler, next: () => Promise ) { - await next() + await next(); - const nodeGypMarker = "'lib/fs.js'," + const nodeGypMarker = "'lib/fs.js',"; await replaceInFileAsync( - 'node.gyp', + "node.gyp", nodeGypMarker, ` ${nodeGypMarker} ${files - .filter((x) => x.filename.startsWith('lib')) + .filter((x) => x.filename.startsWith("lib")) .map((x) => `'${x.filename}'`) .toString()}, `.trim() - ) + ); } diff --git a/src/patches/ico.ts b/src/patches/ico.ts index df4fb43..d19ca38 100644 --- a/src/patches/ico.ts +++ b/src/patches/ico.ts @@ -1,12 +1,18 @@ -import { normalize } from 'path' -import { readFileAsync } from '../util' -import { NexeCompiler } from '../compiler' +import { normalize } from "path"; +import { readFileAsync } from "../util"; +import { NexeCompiler } from "../compiler"; -export default async function ico(compiler: NexeCompiler, next: () => Promise) { - const iconFile = compiler.options.ico +export default async function ico( + compiler: NexeCompiler, + next: () => Promise +) { + const iconFile = compiler.options.ico; if (!iconFile) { - return next() + return next(); } - await compiler.setFileContentsAsync('src/res/node.ico', await readFileAsync(normalize(iconFile))) - return next() + await compiler.setFileContentsAsync( + "src/res/node.ico", + await readFileAsync(normalize(iconFile)) + ); + return next(); } diff --git a/src/patches/index.ts b/src/patches/index.ts index 8697313..6acb98b 100644 --- a/src/patches/index.ts +++ b/src/patches/index.ts @@ -1,12 +1,12 @@ -import gyp from './gyp' -import bootNexe from './third-party-main' -import buildFixes from './build-fixes' -import cli from './disable-node-cli' -import flags from './flags' -import ico from './ico' -import rc from './node-rc' -import snapshot from './snapshot' +import gyp from "./gyp"; +import bootNexe from "./third-party-main"; +import buildFixes from "./build-fixes"; +import cli from "./disable-node-cli"; +import flags from "./flags"; +import ico from "./ico"; +import rc from "./node-rc"; +import snapshot from "./snapshot"; -const patches = [gyp, bootNexe, buildFixes, cli, flags, ico, rc, snapshot] +const patches = [gyp, bootNexe, buildFixes, cli, flags, ico, rc, snapshot]; -export default patches +export default patches; diff --git a/src/patches/node-rc.ts b/src/patches/node-rc.ts index a729c02..d8b250d 100644 --- a/src/patches/node-rc.ts +++ b/src/patches/node-rc.ts @@ -1,28 +1,31 @@ -import { NexeCompiler } from '../compiler' +import { NexeCompiler } from "../compiler"; -export default async function nodeRc(compiler: NexeCompiler, next: () => Promise) { - const options = compiler.options.rc +export default async function nodeRc( + compiler: NexeCompiler, + next: () => Promise +) { + const options = compiler.options.rc; if (!options) { - return next() + return next(); } - const file = await compiler.readFileAsync('src/res/node.rc') + const file = await compiler.readFileAsync("src/res/node.rc"); Object.keys(options).forEach((key) => { - let value = options[key] - const isVar = /^[A-Z_]+$/.test(value) - value = isVar ? value : `"${value}"` + let value = options[key]; + const isVar = /^[A-Z_]+$/.test(value); + value = isVar ? value : `"${value}"`; file.contents = file.contents .toString() - .replace(new RegExp(`VALUE "${key}",.*`), `VALUE "${key}", ${value}`) - }) - ;['PRODUCTVERSION', 'FILEVERSION'].forEach((x) => { + .replace(new RegExp(`VALUE "${key}",.*`), `VALUE "${key}", ${value}`); + }); + ["PRODUCTVERSION", "FILEVERSION"].forEach((x) => { if (options[x]) { file.contents = file.contents .toString() - .replace(new RegExp(x + ' .*$', 'm'), `${x} ${options[x]}`) + .replace(new RegExp(x + " .*$", "m"), `${x} ${options[x]}`); } - }) + }); - return next() + return next(); } diff --git a/src/patches/snapshot.ts b/src/patches/snapshot.ts index c00d1d7..4ca6da5 100644 --- a/src/patches/snapshot.ts +++ b/src/patches/snapshot.ts @@ -1,19 +1,24 @@ -import { resolve } from 'path' -import { NexeCompiler } from '../compiler' -import { semverGt } from '../util' +import { resolve } from "path"; +import { NexeCompiler } from "../compiler"; +import { semverGt } from "../util"; -export default async function (compiler: NexeCompiler, next: () => Promise) { - const { snapshot, warmup, cwd } = compiler.options +export default async function ( + compiler: NexeCompiler, + next: () => Promise +) { + const { snapshot, warmup, cwd } = compiler.options; if (!snapshot) { - return next() + return next(); } - const variablePrefix = semverGt(compiler.target.version, '11.0.0') ? 'v8_' : '' + const variablePrefix = semverGt(compiler.target.version, "11.0.0") + ? "v8_" + : ""; await compiler.replaceInFileAsync( compiler.configureScript, - 'def configure_v8(o):', + "def configure_v8(o):", `def configure_v8(o):\n o['variables']['${variablePrefix}embed_script'] = r'${resolve( cwd, snapshot @@ -21,7 +26,7 @@ export default async function (compiler: NexeCompiler, next: () => Promise cwd, warmup || snapshot )}'` - ) + ); - return next() + return next(); } diff --git a/src/patches/third-party-main.ts b/src/patches/third-party-main.ts index 3629320..2a44ec5 100644 --- a/src/patches/third-party-main.ts +++ b/src/patches/third-party-main.ts @@ -1,40 +1,43 @@ -import { NexeCompiler } from '../compiler' -import { parse } from 'meriyah' -import { wrap, semverGt } from '../util' +import { NexeCompiler } from "../compiler"; +import { parse } from "meriyah"; +import { wrap, semverGt } from "../util"; function walkSome(node: any, visit: Function) { - if (!node || typeof node.type !== 'string' || node._visited) { - return false + if (!node || typeof node.type !== "string" || node._visited) { + return false; } - visit(node) - node._visited = true - for (let childNode in node) { - const child = node[childNode] + visit(node); + node._visited = true; + for (const childNode in node) { + const child = node[childNode]; if (Array.isArray(child)) { for (let i = 0; i < child.length; i++) { if (walkSome(child[i], visit)) { - return true + return true; } } } else if (walkSome(child, visit)) { - return true + return true; } } - return false + return false; } -export default async function main(compiler: NexeCompiler, next: () => Promise) { - let bootFile = 'lib/internal/bootstrap_node.js' - const { version } = compiler.target +export default async function main( + compiler: NexeCompiler, + next: () => Promise +) { + let bootFile = "lib/internal/bootstrap_node.js"; + const { version } = compiler.target; - if (version.startsWith('4.')) { - bootFile = 'src/node.js' - } else if (semverGt(version, '18.11.99')) { - bootFile = 'lib/internal/process/pre_execution.js' - } else if (semverGt(version, '11.99')) { - bootFile = 'lib/internal/bootstrap/pre_execution.js' - } else if (semverGt(version, '9.10.1')) { - bootFile = 'lib/internal/bootstrap/node.js' + if (version.startsWith("4.")) { + bootFile = "src/node.js"; + } else if (semverGt(version, "18.11.99")) { + bootFile = "lib/internal/process/pre_execution.js"; + } else if (semverGt(version, "11.99")) { + bootFile = "lib/internal/bootstrap/pre_execution.js"; + } else if (semverGt(version, "9.10.1")) { + bootFile = "lib/internal/bootstrap/node.js"; } const file = await compiler.readFileAsync(bootFile), @@ -42,77 +45,79 @@ export default async function main(compiler: NexeCompiler, next: () => Promise { - if (!location.start.line && node.type === 'BlockStatement') { + if (!location.start.line && node.type === "BlockStatement") { //Find the first block statement and mark the location - Object.assign(location, node.loc) - return true + Object.assign(location, node.loc); + return true; } - }) + }); - const fileLines = file.contents.toString().split('\n') - if (semverGt(version, '18.16.99')) { + const fileLines = file.contents.toString().split("\n"); + if (semverGt(version, "18.16.99")) { await compiler.replaceInFileAsync( - 'lib/internal/modules/cjs/loader.js', + "lib/internal/modules/cjs/loader.js", "'use strict';", - "'use strict';\n" + '{{ file("lib/fs/bootstrap.js") }}' + '\n' - ) - fileLines.splice(location.start.line, 0, 'expandArgv1 = false;') + "'use strict';\n" + '{{ file("lib/fs/bootstrap.js") }}' + "\n" + ); + fileLines.splice(location.start.line, 0, "expandArgv1 = false;"); } else { fileLines.splice( location.start.line, 0, '{{ file("lib/fs/bootstrap.js") }}' + - '\n' + - (semverGt(version, '11.99') ? 'expandArgv1 = false;\n' : '') - ) + "\n" + + (semverGt(version, "11.99") ? "expandArgv1 = false;\n" : "") + ); } - file.contents = fileLines.join('\n') + file.contents = fileLines.join("\n"); - if (semverGt(version, '11.99')) { - if (semverGt(version, '12.17.99')) { + if (semverGt(version, "11.99")) { + if (semverGt(version, "12.17.99")) { await compiler.replaceInFileAsync( bootFile, - 'initializeFrozenIntrinsics();', - 'initializeFrozenIntrinsics();\n' + wrap('{{ file("lib/patches/boot-nexe.js") }}') - ) + "initializeFrozenIntrinsics();", + "initializeFrozenIntrinsics();\n" + + wrap('{{ file("lib/patches/boot-nexe.js") }}') + ); } else { await compiler.replaceInFileAsync( bootFile, - 'initializePolicy();', - 'initializePolicy();\n' + wrap('{{ file("lib/patches/boot-nexe.js") }}') - ) + "initializePolicy();", + "initializePolicy();\n" + wrap('{{ file("lib/patches/boot-nexe.js") }}') + ); } await compiler.replaceInFileAsync( bootFile, - 'assert(!CJSLoader.hasLoadedAnyUserCJSModule)', - '/*assert(!CJSLoader.hasLoadedAnyUserCJSModule)*/' - ) - const { contents: nodeccContents } = await compiler.readFileAsync('src/node.cc') - if (nodeccContents.includes('if (env->worker_context() != nullptr) {')) { + "assert(!CJSLoader.hasLoadedAnyUserCJSModule)", + "/*assert(!CJSLoader.hasLoadedAnyUserCJSModule)*/" + ); + const { contents: nodeccContents } = await compiler.readFileAsync( + "src/node.cc" + ); + if (nodeccContents.includes("if (env->worker_context() != nullptr) {")) { await compiler.replaceInFileAsync( - 'src/node.cc', - 'if (env->worker_context() != nullptr) {', - 'if (env->worker_context() == nullptr) {\n' + + "src/node.cc", + "if (env->worker_context() != nullptr) {", + "if (env->worker_context() == nullptr) {\n" + ' return StartExecution(env, "internal/main/run_main_module"); } else {\n' - ) + ); } else { await compiler.replaceInFileAsync( - 'src/node.cc', - 'MaybeLocal StartMainThreadExecution(Environment* env) {', - 'MaybeLocal StartMainThreadExecution(Environment* env) {\n' + + "src/node.cc", + "MaybeLocal StartMainThreadExecution(Environment* env) {", + "MaybeLocal StartMainThreadExecution(Environment* env) {\n" + ' return StartExecution(env, "internal/main/run_main_module");\n' - ) + ); } } else { await compiler.setFileContentsAsync( - 'lib/_third_party_main.js', + "lib/_third_party_main.js", '{{ file("lib/patches/boot-nexe.js") }}' - ) + ); } - return next() + return next(); } diff --git a/src/releases.ts b/src/releases.ts index 2cb98a0..9737ecc 100644 --- a/src/releases.ts +++ b/src/releases.ts @@ -1,23 +1,31 @@ -import axios from 'axios'; -import { platforms, architectures, NexeTarget, getTarget, targetsEqual } from './target' -export { NexeTarget } +import axios from "axios"; +import { + platforms, + architectures, + NexeTarget, + getTarget, + targetsEqual, +} from "./target"; +export { NexeTarget }; -const versionsToSkip = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 17, 19, 21, 22] +const versionsToSkip = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 17, 19, 21, 22, +]; export interface GitAsset { - name: string - url: string - browser_download_url: string + name: string; + url: string; + browser_download_url: string; } export interface GitRelease { - tag_name: string - assets_url: string - upload_url: string - assets: GitAsset[] + tag_name: string; + assets_url: string; + upload_url: string; + assets: GitAsset[]; } interface NodeRelease { - version: string + version: string; } async function getJson(url: string, options?: any): Promise { @@ -26,38 +34,43 @@ async function getJson(url: string, options?: any): Promise { } function isBuildableVersion(version: string) { - if (version === '12.11.0') { - return false + if (version === "12.11.0") { + return false; } - return !versionsToSkip.includes(Number(version.split('.')[0])) + return !versionsToSkip.includes(Number(version.split(".")[0])); } export function getLatestGitRelease(options?: any): Promise { - return getJson('https://api.github.com/repos/nexe/nexe/releases/latest', options) + return getJson( + "https://api.github.com/repos/nexe/nexe/releases/latest", + options + ); } export async function getUnBuiltReleases(options?: any) { const nodeReleases = await getJson( - 'https://nodejs.org/download/release/index.json' - ) - const existingVersions = (await getLatestGitRelease(options)).assets.map((x) => getTarget(x.name)) + "https://nodejs.org/download/release/index.json" + ); + const existingVersions = (await getLatestGitRelease(options)).assets.map( + (x) => getTarget(x.name) + ); - const versionMap: { [key: string]: true } = {} + const versionMap: { [key: string]: true } = {}; return nodeReleases .reduce((versions: NexeTarget[], { version }) => { - version = version.replace('v', '').trim() + version = version.replace("v", "").trim(); if (!isBuildableVersion(version) || versionMap[version]) { - return versions + return versions; } - versionMap[version] = true + versionMap[version] = true; platforms.forEach((platform) => { architectures.forEach((arch) => { - if (arch === 'x86' && platform === 'mac') return - if (arch.includes('arm')) return - versions.push(getTarget({ platform, arch, version })) - }) - }) - return versions + if (arch === "x86" && platform === "mac") return; + if (arch.includes("arm")) return; + versions.push(getTarget({ platform, arch, version })); + }); + }); + return versions; }, []) - .filter((x) => !existingVersions.some((t) => targetsEqual(t, x))) + .filter((x) => !existingVersions.some((t) => targetsEqual(t, x))); } diff --git a/src/steps/artifacts.ts b/src/steps/artifacts.ts index f06439c..e8e7455 100644 --- a/src/steps/artifacts.ts +++ b/src/steps/artifacts.ts @@ -1,33 +1,35 @@ -import { join, dirname } from 'path' -import * as fs from 'fs' -import { promisify } from 'util' -import { readFileAsync, writeFileAsync, isDirectoryAsync } from '../util' -import mkdirpAsync = require('mkdirp') -import { NexeCompiler } from '../compiler' +import { join, dirname } from "path"; +import * as fs from "fs"; +import { promisify } from "util"; +import { readFileAsync, writeFileAsync, isDirectoryAsync } from "../util"; +import mkdirpAsync = require("mkdirp"); +import { NexeCompiler } from "../compiler"; const unlinkAsync = promisify(fs.unlink), - readdirAsync = promisify(fs.readdir) + readdirAsync = promisify(fs.readdir); function readDirAsync(dir: string): Promise { return readdirAsync(dir).then((paths) => { return Promise.all( paths.map((file: string) => { - const path = join(dir, file) - return isDirectoryAsync(path).then((x) => (x ? readDirAsync(path) : (path as any))) + const path = join(dir, file); + return isDirectoryAsync(path).then((x) => + x ? readDirAsync(path) : (path as any) + ); }) ).then((result) => { - return [].concat(...(result as any)) - }) - }) + return [].concat(...(result as any)); + }); + }); } function maybeReadFileContentsAsync(file: string) { - return readFileAsync(file, 'utf-8').catch((e) => { - if (e.code === 'ENOENT') { - return '' + return readFileAsync(file, "utf-8").catch((e) => { + if (e.code === "ENOENT") { + return ""; } - throw e - }) + throw e; + }); } /** @@ -39,30 +41,36 @@ function maybeReadFileContentsAsync(file: string) { * - Original versions of sources to be patched are written to the temporary directory * - Finally, The patched files are written into source. */ -export default async function artifacts(compiler: NexeCompiler, next: () => Promise) { - const { src } = compiler - const temp = join(src, 'nexe') - await mkdirpAsync(temp) - const tmpFiles = await readDirAsync(temp) +export default async function artifacts( + compiler: NexeCompiler, + next: () => Promise +) { + const { src } = compiler; + const temp = join(src, "nexe"); + await mkdirpAsync(temp); + const tmpFiles = await readDirAsync(temp); await Promise.all( tmpFiles.map(async (path) => { - return compiler.writeFileAsync(path.replace(temp, ''), await readFileAsync(path, 'utf-8')) + return compiler.writeFileAsync( + path.replace(temp, ""), + await readFileAsync(path, "utf-8") + ); }) - ) + ); - await next() + await next(); - await Promise.all(tmpFiles.map((x) => unlinkAsync(x))) + await Promise.all(tmpFiles.map((x) => unlinkAsync(x))); return Promise.all( compiler.files.map(async (file) => { - const sourceFile = join(src, file.filename) - const tempFile = join(temp, file.filename) - const fileContents = await maybeReadFileContentsAsync(sourceFile) + const sourceFile = join(src, file.filename); + const tempFile = join(temp, file.filename); + const fileContents = await maybeReadFileContentsAsync(sourceFile); - await mkdirpAsync(dirname(tempFile)) - await writeFileAsync(tempFile, fileContents) - await compiler.writeFileAsync(file.filename, file.contents) + await mkdirpAsync(dirname(tempFile)); + await writeFileAsync(tempFile, fileContents); + await compiler.writeFileAsync(file.filename, file.contents); }) - ) + ); } diff --git a/src/steps/bundle.ts b/src/steps/bundle.ts index c77d60e..e1685f5 100644 --- a/src/steps/bundle.ts +++ b/src/steps/bundle.ts @@ -1,88 +1,95 @@ -import { NexeCompiler, NexeError } from '../compiler' -import { resolve, relative } from 'path' -import resolveFiles, { resolveSync } from 'resolve-dependencies' -import { dequote, STDIN_FLAG, semverGt, each } from '../util' -import { Readable } from 'stream' +import { NexeCompiler, NexeError } from "../compiler"; +import { resolve, relative } from "path"; +import resolveFiles, { resolveSync } from "resolve-dependencies"; +import { dequote, STDIN_FLAG, semverGt, each } from "../util"; +import { Readable } from "stream"; function getStdIn(stdin: Readable): Promise { - let out = '' + let out = ""; return new Promise((resolve) => { stdin - .setEncoding('utf8') - .on('readable', () => { - let current + .setEncoding("utf8") + .on("readable", () => { + let current; while ((current = stdin.read())) { - out += current + out += current; } }) - .on('end', () => resolve(out.trim())) + .on("end", () => resolve(out.trim())); setTimeout(() => { if (!out.trim()) { - resolve(out.trim()) + resolve(out.trim()); } - }, 1000) - }) + }, 1000); + }); } export default async function bundle(compiler: NexeCompiler, next: any) { - const { bundle: doBundle, cwd, input: inputPath } = compiler.options - let input = inputPath - compiler.entrypoint = './' + relative(cwd, input) + const { bundle: doBundle, cwd, input: inputPath } = compiler.options; + let input = inputPath; + compiler.entrypoint = "./" + relative(cwd, input); - if (semverGt(compiler.target.version, '11.99')) { - compiler.startup = '' + if (semverGt(compiler.target.version, "11.99")) { + compiler.startup = ""; } else { - compiler.startup = ';require("module").runMain();' + compiler.startup = ';require("module").runMain();'; } if (!doBundle) { - await compiler.addResource(resolve(cwd, input)) - return next() + await compiler.addResource(resolve(cwd, input)); + return next(); } - let code = '' - if (typeof doBundle === 'string') { - code = await require(doBundle).createBundle(compiler.options) + let code = ""; + if (typeof doBundle === "string") { + code = await require(doBundle).createBundle(compiler.options); } - if (input === STDIN_FLAG && (code = code || dequote(await getStdIn(process.stdin)))) { - compiler.stdinUsed = true - compiler.entrypoint = './__nexe_stdin.js' - await compiler.addResource(resolve(cwd, compiler.entrypoint), code) - return next() + if ( + input === STDIN_FLAG && + (code = code || dequote(await getStdIn(process.stdin))) + ) { + compiler.stdinUsed = true; + compiler.entrypoint = "./__nexe_stdin.js"; + await compiler.addResource(resolve(cwd, compiler.entrypoint), code); + return next(); } if (input === STDIN_FLAG) { - const maybeInput = resolveSync(cwd, '.') + const maybeInput = resolveSync(cwd, "."); if (!maybeInput || !maybeInput.absPath) { - throw new NexeError('No valid input detected') + throw new NexeError("No valid input detected"); } - input = maybeInput.absPath - compiler.entrypoint = './' + relative(cwd, input) + input = maybeInput.absPath; + compiler.entrypoint = "./" + relative(cwd, input); } - const step = compiler.log.step('Resolving dependencies...') + const step = compiler.log.step("Resolving dependencies..."); const { files, warnings } = await resolveFiles( input, - ...Object.keys(compiler.bundle.list).filter((x) => x.endsWith('.js') || x.endsWith('.mjs')), - { cwd, expand: 'variable', loadContent: false } - ) + ...Object.keys(compiler.bundle.list).filter( + (x) => x.endsWith(".js") || x.endsWith(".mjs") + ), + { cwd, expand: "variable", loadContent: false } + ); if ( - warnings.filter((x) => x.startsWith('Error parsing file') && !x.includes('node_modules')).length + warnings.filter( + (x) => x.startsWith("Error parsing file") && !x.includes("node_modules") + ).length ) { - throw new NexeError('Parsing Error:\n' + warnings.join('\n')) + throw new NexeError("Parsing Error:\n" + warnings.join("\n")); } //TODO: warnings.forEach((x) => console.log(x)) await Promise.all( Object.entries(files).map(([key]) => { - step.log(`Including dependency: ${key}`) - return compiler.addResource(key) + step.log(`Including dependency: ${key}`); + return compiler.addResource(key); }) - ) + ); - return next() + return next(); } diff --git a/src/steps/clean.ts b/src/steps/clean.ts index 5f1570b..ba557aa 100644 --- a/src/steps/clean.ts +++ b/src/steps/clean.ts @@ -1,19 +1,24 @@ -import { NexeCompiler } from '../compiler' -import { rimrafAsync } from '../util' -import { NexeTarget } from '../target' +import { NexeCompiler } from "../compiler"; +import { rimrafAsync } from "../util"; +import { NexeTarget } from "../target"; -export default async function clean(compiler: NexeCompiler, next: () => Promise) { - const { options } = compiler +export default async function clean( + compiler: NexeCompiler, + next: () => Promise +) { + const { options } = compiler; if (options.clean) { - let path = compiler.src + let path = compiler.src; if (!options.build) { - path = compiler.getNodeExecutableLocation(compiler.options.targets[0] as NexeTarget) + path = compiler.getNodeExecutableLocation( + compiler.options.targets[0] as NexeTarget + ); } - const step = compiler.log.step('Cleaning up nexe build artifacts...') - step.log(`Deleting contents at: ${path}`) - await rimrafAsync(path) - step.log(`Deleted contents at: ${path}`) - return compiler.quit() + const step = compiler.log.step("Cleaning up nexe build artifacts..."); + step.log(`Deleting contents at: ${path}`); + await rimrafAsync(path); + step.log(`Deleted contents at: ${path}`); + return compiler.quit(); } - return next() + return next(); } diff --git a/src/steps/cli.ts b/src/steps/cli.ts index 921f191..a731ec3 100644 --- a/src/steps/cli.ts +++ b/src/steps/cli.ts @@ -1,11 +1,17 @@ -import { platform } from 'os' -import { dirname, normalize, relative, resolve } from 'path' -import { createWriteStream, chmodSync, statSync, readFileSync, writeFileSync } from 'fs' -import { NexeCompiler } from '../compiler' -import { NexeTarget } from '../target' -import { STDIN_FLAG } from '../util' -import { patchMachOExecutable } from './mach-o' -import mkdirp = require('mkdirp') +import { platform } from "os"; +import { dirname, normalize, relative, resolve } from "path"; +import { + createWriteStream, + chmodSync, + statSync, + readFileSync, + writeFileSync, +} from "fs"; +import { NexeCompiler } from "../compiler"; +import { NexeTarget } from "../target"; +import { STDIN_FLAG } from "../util"; +import { patchMachOExecutable } from "./mach-o"; +import mkdirp = require("mkdirp"); /** * The "cli" step detects the appropriate input. If no input options are passed, @@ -17,50 +23,54 @@ import mkdirp = require('mkdirp') * @param {*} compiler * @param {*} next */ -export default async function cli(compiler: NexeCompiler, next: () => Promise) { - await next() +export default async function cli( + compiler: NexeCompiler, + next: () => Promise +) { + await next(); const { log } = compiler, target = compiler.options.targets.shift() as NexeTarget, deliverable = await compiler.compileAsync(target), - output = normalize(compiler.output!) + output = normalize(compiler.output!); - mkdirp.sync(dirname(output)) + mkdirp.sync(dirname(output)); return new Promise((res, rej) => { - const step = log.step('Writing result to file') + const step = log.step("Writing result to file"); deliverable .pipe(createWriteStream(output)) - .on('error', rej) - .once('close', (e: Error) => { - if (e) { - rej(e) - } else if (compiler.output) { + .on("error", rej) + .once("close", () => { + if (compiler.output) { const output = compiler.output, mode = statSync(output).mode | 0o111, inputFileLogOutput = relative( process.cwd(), - resolve(compiler.options.cwd, compiler.entrypoint || compiler.options.input) + resolve( + compiler.options.cwd, + compiler.entrypoint || compiler.options.input + ) ), - outputFileLogOutput = relative(process.cwd(), output) + outputFileLogOutput = relative(process.cwd(), output); - if (platform() === 'darwin') { - step.log('Preparing binary for macOS signing.') - writeFileSync(output, patchMachOExecutable(readFileSync(output))) + if (platform() === "darwin") { + step.log("Preparing binary for macOS signing."); + writeFileSync(output, patchMachOExecutable(readFileSync(output))); } - chmodSync(output, mode.toString(8).slice(-3)) + chmodSync(output, mode.toString(8).slice(-3)); step.log( `Entry: '${ compiler.stdinUsed ? compiler.options.mangle ? STDIN_FLAG - : '[none]' + : "[none]" : inputFileLogOutput }' written to: ${outputFileLogOutput}` - ) - compiler.quit() - res(output) + ); + compiler.quit(); + res(output); } - }) - }) + }); + }); } diff --git a/src/steps/download.ts b/src/steps/download.ts index 0898b8c..61fc769 100644 --- a/src/steps/download.ts +++ b/src/steps/download.ts @@ -1,75 +1,86 @@ -import axios, { AxiosResponse } from 'axios' -import { pathExistsAsync } from '../util' -import { LogStep } from '../logger' -import { IncomingMessage } from 'http' -import { NexeCompiler, NexeError } from '../compiler' -import { dirname } from 'path' -import { createWriteStream } from 'fs' -import { pipeline } from 'stream/promises' -import { createBrotliDecompress, createGunzip, createInflate } from 'zlib' -import tar from 'tar' -import fs from 'fs/promises' +import axios, { AxiosResponse } from "axios"; +import { pathExistsAsync } from "../util"; +import { LogStep } from "../logger"; +import { IncomingMessage } from "http"; +import { NexeCompiler, NexeError } from "../compiler"; +import { dirname } from "path"; +import { createWriteStream } from "fs"; +import { pipeline } from "stream/promises"; +import { createBrotliDecompress, createGunzip, createInflate } from "zlib"; +import tar from "tar"; +import fs from "fs/promises"; -async function downloadWithProgress(url: string, dest: string, options: any = {}, step?: LogStep): Promise { +async function downloadWithProgress( + url: string, + dest: string, + options: any = {}, + step?: LogStep +): Promise { const response = await axios({ url, - method: 'GET', - responseType: 'stream', - ...options - }) + method: "GET", + responseType: "stream", + ...options, + }); - const total = parseInt(response.headers['content-length'] || '0', 10) - let current = 0 + const total = parseInt(response.headers["content-length"] || "0", 10); + let current = 0; // Create write stream - const writer = createWriteStream(dest) + const writer = createWriteStream(dest); // Handle progress - response.data.on('data', (chunk: Buffer) => { - current += chunk.length + response.data.on("data", (chunk: Buffer) => { + current += chunk.length; if (step && total > 0) { - step.modify(`Downloading...${((current / total) * 100).toFixed()}%`) + step.modify(`Downloading...${((current / total) * 100).toFixed()}%`); } - }) + }); // Pipe the response to file - await pipeline(response.data, writer) + await pipeline(response.data, writer); if (step) { - step.log(`Download completed: ${dest}`) + step.log(`Download completed: ${dest}`); } } -async function fetchNodeSourceAsync(dest: string, url: string, step: LogStep, options = {}) { - const setText = (p: number) => step.modify(`Downloading Node: ${p.toFixed()}%...`) +async function fetchNodeSourceAsync( + dest: string, + url: string, + step: LogStep, + options = {} +) { + const setText = (p: number) => + step.modify(`Downloading Node: ${p.toFixed()}%...`); // Download the file first - const tempFile = dest + '.tar.gz' + const tempFile = dest + ".tar.gz"; const response = await axios({ url, - method: 'GET', - responseType: 'stream', - ...options - }) + method: "GET", + responseType: "stream", + ...options, + }); - const total = parseInt(response.headers['content-length'] || '0', 10) - let current = 0 + const total = parseInt(response.headers["content-length"] || "0", 10); + let current = 0; // Create write stream for the temp file - const writer = createWriteStream(tempFile) + const writer = createWriteStream(tempFile); // Track progress - response.data.on('data', (chunk: Buffer) => { - current += chunk.length + response.data.on("data", (chunk: Buffer) => { + current += chunk.length; if (total > 0) { - setText((current / total) * 100) + setText((current / total) * 100); } - }) + }); // Wait for download to complete - await pipeline(response.data, writer) + await pipeline(response.data, writer); - step.log('Extracting Node...') + step.log("Extracting Node..."); // Extract the tar.gz file await pipeline( @@ -77,27 +88,34 @@ async function fetchNodeSourceAsync(dest: string, url: string, step: LogStep, op createGunzip(), tar.extract({ cwd: dest, - strip: 1 + strip: 1, }) - ) + ); // Clean up temp file - await fs.unlink(tempFile) + await fs.unlink(tempFile); - step.log(`Node source extracted to: ${dest}`) + step.log(`Node source extracted to: ${dest}`); } async function fetchPrebuiltBinary(compiler: NexeCompiler, step: any) { const { target, remoteAsset } = compiler, - filename = compiler.getNodeExecutableLocation(target) + filename = compiler.getNodeExecutableLocation(target); try { - await downloadWithProgress(remoteAsset, filename, compiler.options.downloadOptions, step) + await downloadWithProgress( + remoteAsset, + filename, + compiler.options.downloadOptions, + step + ); } catch (e: any) { if (e.response?.status === 404) { - throw new NexeError(`${remoteAsset} is not available, create it using the --build flag`) + throw new NexeError( + `${remoteAsset} is not available, create it using the --build flag` + ); } else { - throw new NexeError('Error downloading prebuilt binary: ' + e.message) + throw new NexeError("Error downloading prebuilt binary: " + e.message); } } } @@ -107,32 +125,41 @@ async function fetchPrebuiltBinary(compiler: NexeCompiler, step: any) { * @param {*} compiler * @param {*} next */ -export default async function downloadNode(compiler: NexeCompiler, next: () => Promise) { +export default async function downloadNode( + compiler: NexeCompiler, + next: () => Promise +) { const { src, log, target } = compiler, { version } = target, { sourceUrl, downloadOptions, build } = compiler.options, - url = sourceUrl || `https://nodejs.org/dist/v${version}/node-v${version}.tar.gz`, + url = + sourceUrl || + `https://nodejs.org/dist/v${version}/node-v${version}.tar.gz`, step = log.step( - `Downloading ${build ? '' : 'pre-built'} Node.js ${build ? `source from: ${url}` : ''}` + `Downloading ${build ? "" : "pre-built"} Node.js ${ + build ? `source from: ${url}` : "" + }` ), - exeLocation = compiler.getNodeExecutableLocation(build ? undefined : target), - downloadExists = await pathExistsAsync(build ? src : exeLocation) + exeLocation = compiler.getNodeExecutableLocation( + build ? undefined : target + ), + downloadExists = await pathExistsAsync(build ? src : exeLocation); if (downloadExists) { - step.log('Already downloaded...') - return next() + step.log("Already downloaded..."); + return next(); } if (build) { - await fetchNodeSourceAsync(src, url, step, downloadOptions) + await fetchNodeSourceAsync(src, url, step, downloadOptions); } else { - await fetchPrebuiltBinary(compiler, step) + await fetchPrebuiltBinary(compiler, step); } - return next() + return next(); } // Helper function to create a readable stream function createReadStream(path: string) { - return require('fs').createReadStream(path) + return require("fs").createReadStream(path); } diff --git a/src/steps/mach-o.ts b/src/steps/mach-o.ts index 9ffc5c8..161301c 100644 --- a/src/steps/mach-o.ts +++ b/src/steps/mach-o.ts @@ -27,7 +27,7 @@ function parseCStr(buf: Buffer) { for (let i = 0; i < buf.length; i += 1) { if (buf[i] === 0) { - return buf.slice(0, i).toString() + return buf.slice(0, i).toString(); } } } @@ -35,50 +35,50 @@ function parseCStr(buf: Buffer) { function patchCommand(type: number, buf: Buffer, file: Buffer) { // segment_64 if (type === 0x19) { - const name = parseCStr(buf.slice(0, 16)) + const name = parseCStr(buf.slice(0, 16)); - if (name === '__LINKEDIT') { - const fileoff = buf.readBigUInt64LE(32) - const vmsizePatched = BigInt(file.length) - fileoff - const filesizePatched = vmsizePatched + if (name === "__LINKEDIT") { + const fileoff = buf.readBigUInt64LE(32); + const vmsizePatched = BigInt(file.length) - fileoff; + const filesizePatched = vmsizePatched; - buf.writeBigUInt64LE(vmsizePatched, 24) - buf.writeBigUInt64LE(filesizePatched, 40) + buf.writeBigUInt64LE(vmsizePatched, 24); + buf.writeBigUInt64LE(filesizePatched, 40); } } // symtab if (type === 0x2) { - const stroff = buf.readUInt32LE(8) - const strsizePatched = file.length - stroff + const stroff = buf.readUInt32LE(8); + const strsizePatched = file.length - stroff; - buf.writeUInt32LE(strsizePatched, 12) + buf.writeUInt32LE(strsizePatched, 12); } } function patchMachOExecutable(file: Buffer) { - const align = 8 - const hsize = 32 + const align = 8; + const hsize = 32; - const ncmds = file.readUInt32LE(16) - const buf = file.slice(hsize) + const ncmds = file.readUInt32LE(16); + const buf = file.slice(hsize); for (let offset = 0, i = 0; i < ncmds; i += 1) { - const type = buf.readUInt32LE(offset) + const type = buf.readUInt32LE(offset); - offset += 4 - const size = buf.readUInt32LE(offset) - 8 + offset += 4; + const size = buf.readUInt32LE(offset) - 8; - offset += 4 - patchCommand(type, buf.slice(offset, offset + size), file) + offset += 4; + patchCommand(type, buf.slice(offset, offset + size), file); - offset += size + offset += size; if (offset & align) { - offset += align - (offset & align) + offset += align - (offset & align); } } - return file + return file; } -export { patchMachOExecutable } +export { patchMachOExecutable }; diff --git a/src/steps/resource.ts b/src/steps/resource.ts index 91e6f98..cceda55 100644 --- a/src/steps/resource.ts +++ b/src/steps/resource.ts @@ -1,25 +1,33 @@ -import { each } from '../util' -import globs from 'globby' -import { resolve } from 'path' -import { NexeCompiler } from '../compiler' +import { each } from "../util"; +import globs from "globby"; +import { resolve } from "path"; +import { NexeCompiler } from "../compiler"; -export default async function resource(compiler: NexeCompiler, next: () => Promise) { - const { cwd, resources } = compiler.options +export default async function resource( + compiler: NexeCompiler, + next: () => Promise +) { + const { cwd, resources } = compiler.options; if (!resources.length) { - return next() + return next(); } - const step = compiler.log.step('Bundling Resources...') - let count = 0 + const step = compiler.log.step("Bundling Resources..."); + let count = 0; // workaround for https://github.com/sindresorhus/globby/issues/127 // and https://github.com/mrmlnc/fast-glob#pattern-syntax - const resourcesWithForwardSlashes = resources.map((r) => r.replace(/\\/g, '/')) + const resourcesWithForwardSlashes = resources.map((r) => + r.replace(/\\/g, "/") + ); - await each(globs(resourcesWithForwardSlashes, { cwd, onlyFiles: true }), async (file) => { - count++ - step.log(`Including file: ${file}`) - await compiler.addResource(resolve(cwd, file)) - }) - step.log(`Included ${count} file(s)`) - return next() + await each( + globs(resourcesWithForwardSlashes, { cwd, onlyFiles: true }), + async (file) => { + count++; + step.log(`Including file: ${file}`); + await compiler.addResource(resolve(cwd, file)); + } + ); + step.log(`Included ${count} file(s)`); + return next(); } diff --git a/src/steps/shim.ts b/src/steps/shim.ts index e42ee89..12801a4 100644 --- a/src/steps/shim.ts +++ b/src/steps/shim.ts @@ -1,24 +1,27 @@ -import { NexeCompiler } from '../compiler' -import { wrap } from '../util' +import { NexeCompiler } from "../compiler"; +import { wrap } from "../util"; -export default async function (compiler: NexeCompiler, next: () => Promise) { - await next() +export default async function ( + compiler: NexeCompiler, + next: () => Promise +) { + await next(); compiler.shims.push( wrap( [ - 'process.__nexe = {};', - 'const fsPatcher = (function() {', - 'const module = {exports: {}};', - 'const exports = module.exports;', + "process.__nexe = {};", + "const fsPatcher = (function() {", + "const module = {exports: {}};", + "const exports = module.exports;", '{{file("lib/fs/patch.bundle.js")}}', - 'return module.exports;', - '})()', - 'fsPatcher.shimFs(process.__nexe);', - compiler.options.fs ? '' : 'restoreFs();', - ].join('\n') + "return module.exports;", + "})()", + "fsPatcher.shimFs(process.__nexe);", + compiler.options.fs ? "" : "restoreFs();", + ].join("\n") //TODO support only restoring specific methods ) - ) + ); compiler.shims.push( wrap(` if (process.argv[1] && process.env.NODE_UNIQUE_ID) { @@ -27,7 +30,7 @@ export default async function (compiler: NexeCompiler, next: () => Promise delete process.env.NODE_UNIQUE_ID } `) - ) + ); compiler.shims.push( wrap(` @@ -39,5 +42,5 @@ export default async function (compiler: NexeCompiler, next: () => Promise process.argv.splice(1,0, entry) } `) - ) + ); } diff --git a/src/target.ts b/src/target.ts index 3620db7..f55b0d2 100644 --- a/src/target.ts +++ b/src/target.ts @@ -1,96 +1,107 @@ -export type NodePlatform = 'windows' | 'mac' | 'alpine' | 'linux' -export type NodeArch = 'x86' | 'x64' | 'arm' | 'arm64' +export type NodePlatform = "windows" | "mac" | "alpine" | "linux"; +export type NodeArch = "x86" | "x64" | "arm" | "arm64"; -const platforms: NodePlatform[] = ['windows', 'mac', 'alpine', 'linux'], - architectures: NodeArch[] = ['x86', 'x64', 'arm', 'arm64'] +const platforms: NodePlatform[] = ["windows", "mac", "alpine", "linux"], + architectures: NodeArch[] = ["x86", "x64", "arm", "arm64"]; -export { platforms, architectures } +export { platforms, architectures }; export interface NexeTarget { - version: string - platform: NodePlatform | string - arch: NodeArch | string + version: string; + platform: NodePlatform | string; + arch: NodeArch | string; } const prettyPlatform: { [key: string]: NodePlatform } = { - win32: 'windows', - windows: 'windows', - win: 'windows', - darwin: 'mac', - macos: 'mac', - mac: 'mac', - linux: 'linux', - static: 'alpine', - alpine: 'alpine', -} + win32: "windows", + windows: "windows", + win: "windows", + darwin: "mac", + macos: "mac", + mac: "mac", + linux: "linux", + static: "alpine", + alpine: "alpine", +}; const prettyArch: { [key: string]: NodeArch } = { - x86: 'x86', - arm6: 'arm', - arm64: 'arm64', - arm6l: 'arm', - arm: 'arm', - arm7: 'arm', - arm7l: 'arm', - amd64: 'x64', - ia32: 'x86', - x32: 'x86', - x64: 'x64', -} + x86: "x86", + arm6: "arm", + arm64: "arm64", + arm6l: "arm", + arm: "arm", + arm7: "arm", + arm7l: "arm", + amd64: "x64", + ia32: "x86", + x32: "x86", + x64: "x64", +}; function isVersion(x: string) { if (!x) { - return false + return false; } - return /^[\d]+$/.test(x.replace(/v|\.|\s+/g, '')) + return /^[\d]+$/.test(x.replace(/v|\.|\s+/g, "")); } function isPlatform(x: string): x is NodePlatform { - return x in prettyPlatform + return x in prettyPlatform; } function isArch(x: string): x is NodeArch { - return x in prettyArch + return x in prettyArch; } class Target implements NexeTarget { - constructor(public arch: NodeArch, public platform: NodePlatform, public version: string) {} + constructor( + public arch: NodeArch, + public platform: NodePlatform, + public version: string + ) {} toJSON() { - return this.toString() + return this.toString(); } toString() { - return `${this.platform}-${this.arch}-${this.version}` + return `${this.platform}-${this.arch}-${this.version}`; } } export function targetsEqual(a: NexeTarget, b: NexeTarget) { - return a.arch === b.arch && a.platform === b.platform && a.version === b.version + return ( + a.arch === b.arch && a.platform === b.platform && a.version === b.version + ); } -export function getTarget(target: string | Partial = ''): NexeTarget { - const currentArch = process.arch - let arch = currentArch in prettyArch ? prettyArch[process.arch] : (process.arch as NodeArch), +export function getTarget( + target: string | Partial = "" +): NexeTarget { + const currentArch = process.arch; + let arch = + currentArch in prettyArch + ? prettyArch[process.arch] + : (process.arch as NodeArch), platform = prettyPlatform[process.platform], - version = process.version.slice(1) + version = process.version.slice(1); - if (typeof target !== 'string') { - target = `${target.platform}-${target.arch}-${target.version}` + if (typeof target !== "string") { + target = `${target.platform}-${target.arch}-${target.version}`; } target .toLowerCase() - .split('-') + .split("-") .forEach((x) => { if (isVersion(x)) { - version = x.replace(/v/g, '') + version = x.replace(/v/g, ""); } if (isPlatform(x)) { - platform = prettyPlatform[x] + platform = prettyPlatform[x]; } if (isArch(x)) { - arch = prettyArch[x] + arch = prettyArch[x]; } - }) + }); - return new Target(arch, platform, version) + return new Target(arch, platform, version); } diff --git a/src/types.d.ts b/src/types.d.ts index 2856666..f705ee6 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,23 +1,23 @@ -declare module 'got' { +declare module "got" { interface GotFn { - (url: string, options?: any): Promise<{ body: string }> - stream(url: string, optoins?: any): any + (url: string, options?: any): Promise<{ body: string }>; + stream(url: string, optoins?: any): any; } - const got: GotFn - export = got + const got: GotFn; + export = got; } -declare module 'download' { - import { Duplex } from 'stream' +declare module "download" { + import { Duplex } from "stream"; interface DownloadOptions { - extract?: boolean - strip?: number - filename?: string - proxy?: string + extract?: boolean; + strip?: number; + filename?: string; + proxy?: string; } function download( url: string, destination?: string | DownloadOptions, options?: DownloadOptions - ): PromiseLike & Duplex - export = download + ): PromiseLike & Duplex; + export = download; } diff --git a/src/util.ts b/src/util.ts index 83ff194..9ddf4be 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,100 +1,100 @@ -import { readFile, writeFile, stat } from 'fs' -import { execFile } from 'child_process' -import { promisify } from 'util' -import rimraf = require('rimraf') +import { readFile, writeFile, stat } from "fs"; +import { execFile } from "child_process"; +import { promisify } from "util"; +import rimraf = require("rimraf"); -const rimrafAsync = promisify(rimraf) -export const STDIN_FLAG = '[stdin]' +const rimrafAsync = promisify(rimraf); +export const STDIN_FLAG = "[stdin]"; export async function each( list: T[] | Promise, action: (item: T, index: number, list: T[]) => Promise ) { - const l = await list - return Promise.all(l.map(action)) + const l = await list; + return Promise.all(l.map(action)); } export function wrap(code: string) { - return '!(function () {' + code + '})();' + return "!(function () {" + code + "})();"; } function falseOnEnoent(e: any) { - if (e.code === 'ENOENT') { - return false + if (e.code === "ENOENT") { + return false; } - throw e + throw e; } function padRight(str: string, l: number) { - return (str + ' '.repeat(l)).slice(0, l) + return (str + " ".repeat(l)).slice(0, l); } const bound: MethodDecorator = function bound( target: Object, - propertyKey: string | Symbol, + propertyKey: string | symbol, descriptor: TypedPropertyDescriptor ) { - const configurable = true + const configurable = true; return { configurable, get(this: T) { - const value = (descriptor.value as any).bind(this) + const value = (descriptor.value as any).bind(this); Object.defineProperty(this, propertyKey as string, { configurable, value, writable: true, - }) - return value + }); + return value; }, - } -} + }; +}; function dequote(input: string) { - input = input.trim() - const singleQuote = input.startsWith("'") && input.endsWith("'") - const doubleQuote = input.startsWith('"') && input.endsWith('"') + input = input.trim(); + const singleQuote = input.startsWith("'") && input.endsWith("'"); + const doubleQuote = input.startsWith('"') && input.endsWith('"'); if (singleQuote || doubleQuote) { - return input.slice(1).slice(0, -1) + return input.slice(1).slice(0, -1); } - return input + return input; } export interface ReadFileAsync { - (path: string): Promise - (path: string, encoding: string): Promise + (path: string): Promise; + (path: string, encoding: string): Promise; } -const readFileAsync = promisify(readFile) -const writeFileAsync = promisify(writeFile) -const statAsync = promisify(stat) -const execFileAsync = promisify(execFile) -const isWindows = process.platform === 'win32' +const readFileAsync = promisify(readFile); +const writeFileAsync = promisify(writeFile); +const statAsync = promisify(stat); +const execFileAsync = promisify(execFile); +const isWindows = process.platform === "win32"; function pathExistsAsync(path: string) { return statAsync(path) .then((x) => true) - .catch(falseOnEnoent) + .catch(falseOnEnoent); } function isDirectoryAsync(path: string) { return statAsync(path) .then((x) => x.isDirectory()) - .catch(falseOnEnoent) + .catch(falseOnEnoent); } /** * @param version See if this version is greather than the second one * @param operand Version to compare against */ function semverGt(version: string, operand: string) { - const [cMajor, cMinor, cPatch] = version.split('.').map(Number) - let [major, minor, patch] = operand.split('.').map(Number) - if (!minor) minor = 0 - if (!patch) patch = 0 + const [cMajor, cMinor, cPatch] = version.split(".").map(Number); + let [major, minor, patch] = operand.split(".").map(Number); + if (!minor) minor = 0; + if (!patch) patch = 0; return ( cMajor > major || (cMajor === major && cMinor > minor) || (cMajor === major && cMinor === minor && cPatch > patch) - ) + ); } export { @@ -110,4 +110,4 @@ export { pathExistsAsync, isDirectoryAsync, writeFileAsync, -} +}; diff --git a/tasks/build.ts b/tasks/build.ts index ec3a57c..dac307c 100644 --- a/tasks/build.ts +++ b/tasks/build.ts @@ -1,125 +1,140 @@ -import * as nexe from '../lib/nexe' -import { getUnBuiltReleases, getLatestGitRelease } from '../lib/releases' -import { runDockerBuild } from './docker' -import { getTarget, targetsEqual, NexeTarget } from '../lib/target' -import { pathExistsAsync, readFileAsync, execFileAsync, semverGt } from '../lib/util' -import axios from 'axios' -import FormData from 'form-data' -import { cpus } from 'os' +import * as nexe from "../lib/nexe"; +import { getUnBuiltReleases, getLatestGitRelease } from "../lib/releases"; +import { runDockerBuild } from "./docker"; +import { getTarget, targetsEqual, NexeTarget } from "../lib/target"; +import { + pathExistsAsync, + readFileAsync, + execFileAsync, + semverGt, +} from "../lib/util"; +import axios from "axios"; +import FormData from "form-data"; +import { cpus } from "os"; const env = process.env, - isPullRequest = env.BUILD_REASON === 'PullRequest', - isWindows = process.platform === 'win32', - isLinux = process.platform === 'linux', - buildHost = env.AGENT_JOBNAME || (isWindows && 'windows_2017_2015') || '', - isMac = process.platform === 'darwin', + isPullRequest = env.BUILD_REASON === "PullRequest", + isWindows = process.platform === "win32", + isLinux = process.platform === "linux", + buildHost = env.AGENT_JOBNAME || (isWindows && "windows_2017_2015") || "", + isMac = process.platform === "darwin", headers = { - Authorization: 'token ' + env.GITHUB_TOKEN, - 'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)', - } + Authorization: "token " + env.GITHUB_TOKEN, + "User-Agent": "nexe (https://www.npmjs.com/package/nexe)", + }; if (require.main === module) { if (!isPullRequest) { build().catch((x) => { - console.error(x) - process.exit(1) - }) + console.error(x); + process.exit(1); + }); } } async function build() { - const releases = await getUnBuiltReleases({ headers }) + const releases = await getUnBuiltReleases({ headers }); if (!releases.length) { - return + return; } - const windowsBuild = releases.find((x) => x.platform === 'windows'), - macBuild = releases.find((x) => x.platform === 'mac'), - linux = releases.find((x) => x.platform === 'linux'), - alpine = releases.find((x) => x.platform === 'alpine') + const windowsBuild = releases.find((x) => x.platform === "windows"), + macBuild = releases.find((x) => x.platform === "mac"), + linux = releases.find((x) => x.platform === "linux"), + alpine = releases.find((x) => x.platform === "alpine"); - let target: NexeTarget | undefined + let target: NexeTarget | undefined; - if (env.NEXE_VERSION) target = getTarget(env.NEXE_VERSION) - else if (isWindows) target = windowsBuild - else if (isMac) target = macBuild - else if (isLinux) target = linux - if (buildHost.includes('alpine')) target = alpine + if (env.NEXE_VERSION) target = getTarget(env.NEXE_VERSION); + else if (isWindows) target = windowsBuild; + else if (isMac) target = macBuild; + else if (isLinux) target = linux; + if (buildHost.includes("alpine")) target = alpine; if (!target) { - return console.log('Nothing to build...') + return console.log("Nothing to build..."); } - if (isWindows && buildHost.includes('2017') && !semverGt(target.version, '9.99.99')) { - return console.log(`Not building ${target} on this host...`) + if ( + isWindows && + buildHost.includes("2017") && + !semverGt(target.version, "9.99.99") + ) { + return console.log(`Not building ${target} on this host...`); } - if (isWindows && buildHost.includes('2015') && semverGt(target.version, '9.99.99')) { - return console.log(`Not building ${target} on this host...`) + if ( + isWindows && + buildHost.includes("2015") && + semverGt(target.version, "9.99.99") + ) { + return console.log(`Not building ${target} on this host...`); } - const output = isWindows ? './out.exe' : './out', + const output = isWindows ? "./out.exe" : "./out", options = { mangle: false, build: true, verbose: Boolean(env.NEXE_VERBOSE!), target, - make: ['-j' + cpus().length], + make: ["-j" + cpus().length], output, - } - console.log('Building: ' + target + ' on ' + buildHost) - const stop = keepalive() + }; + console.log("Building: " + target + " on " + buildHost); + const stop = keepalive(); if ( - [/*'arm7l', 'arm6l', 'arm64', */ 'alpine'].includes(target.platform) && - buildHost.includes('alpine') + [/*'arm7l', 'arm6l', 'arm64', */ "alpine"].includes(target.platform) && + buildHost.includes("alpine") ) { - await runDockerBuild(target) + await runDockerBuild(target); } else { - await nexe.compile(options) + await nexe.compile(options); } - stop() + stop(); if (await pathExistsAsync(output)) { - await assertNexeBinary(output) + await assertNexeBinary(output); const gitRelease = await getLatestGitRelease({ headers }), - unbuiltReleases = await getUnBuiltReleases({ headers }) + unbuiltReleases = await getUnBuiltReleases({ headers }); if (!unbuiltReleases.some((x) => targetsEqual(x, target!))) { - console.log(`${target} already uploaded.`) - process.exit(0) - return + console.log(`${target} already uploaded.`); + process.exit(0); + return; } // Create form data for file upload const formData = new FormData(); - formData.append('file', await readFileAsync(output), { + formData.append("file", await readFileAsync(output), { filename: target.toString(), - contentType: 'application/octet-stream' + contentType: "application/octet-stream", }); - const uploadUrl = gitRelease.upload_url.split('{')[0]; - await axios.post(uploadUrl, formData, { - params: { name: target.toString() }, - headers: { - ...headers, - ...formData.getHeaders(), - }, - }).catch((reason) => { - console.log(reason && reason.response && reason.response.data) - throw reason - }) - console.log(target + ' uploaded.') - process.exit(0) + const uploadUrl = gitRelease.upload_url.split("{")[0]; + await axios + .post(uploadUrl, formData, { + params: { name: target.toString() }, + headers: { + ...headers, + ...formData.getHeaders(), + }, + }) + .catch((reason) => { + console.log(reason && reason.response && reason.response.data); + throw reason; + }); + console.log(target + " uploaded."); + process.exit(0); } } function keepalive() { - const keepalive = setInterval(() => console.log('Building...'), 300 * 1000) - return () => clearInterval(keepalive) + const keepalive = setInterval(() => console.log("Building..."), 300 * 1000); + return () => clearInterval(keepalive); } function assertNexeBinary(file: string) { return execFileAsync(file).catch((e) => { - if (e && e.stack && e.stack.includes('Invalid Nexe binary')) { - return + if (e && e.stack && e.stack.includes("Invalid Nexe binary")) { + return; } - throw e - }) + throw e; + }); } diff --git a/tasks/docker.ts b/tasks/docker.ts index 3bee81b..2b0d07c 100644 --- a/tasks/docker.ts +++ b/tasks/docker.ts @@ -1,12 +1,12 @@ -import { NexeTarget, architectures } from '../lib/target' -import { writeFileAsync, readFileAsync } from '../lib/util' -import axios from 'axios' -import execa = require('execa') -import { appendFileSync } from 'fs' +import { NexeTarget, architectures } from "../lib/target"; +import { writeFileAsync, readFileAsync } from "../lib/util"; +import axios from "axios"; +import execa = require("execa"); +import { appendFileSync } from "fs"; function alpine(target: NexeTarget) { return ` -FROM ${target.arch === 'x64' ? '' : 'i386/'}alpine:3.12 +FROM ${target.arch === "x64" ? "" : "i386/"}alpine:3.12 RUN apk add --no-cache curl make gcc g++ binutils-gold python linux-headers paxctl libgcc libstdc++ git vim tar gzip wget ENV NODE_VERSION=${target.version} ENV NEXE_VERSION=latest @@ -23,7 +23,7 @@ RUN rm /nexe_temp/\${NODE_VERSION}/out/Release/node && \ npm install -g nexe@\${NEXE_VERSION} RUN echo "console.log('hello world')" >> index.js && \ nexe --build --no-mangle --temp /nexe_temp -c="--fully-static" -o out -`.trim() +`.trim(); } function arm(target: NexeTarget) { @@ -34,30 +34,32 @@ WORKDIR / RUN yarn global add nexe@\${NEXE_VERSION} && \ nexe --build --no-mangle -o out -t ${target.version} -`.trim() +`.trim(); } export async function runDockerBuild(target: NexeTarget) { //todo switch on alpine and arm - const dockerfile = alpine(target) - await writeFileAsync('Dockerfile', dockerfile) - const outFilename = 'nexe-docker-build-log.txt' - await writeFileAsync(outFilename, '') - let output: any = [] + const dockerfile = alpine(target); + await writeFileAsync("Dockerfile", dockerfile); + const outFilename = "nexe-docker-build-log.txt"; + await writeFileAsync(outFilename, ""); + const output: any = []; try { - output.push(await execa(`docker build -t nexe-docker .`, { shell: true })) - output.push(await execa(`docker run -d --name nexe nexe-docker sh`, { shell: true })) - output.push(await execa(`docker cp nexe:/out out`, { shell: true })) - output.push(await execa(`docker rm nexe`, { shell: true })) + output.push(await execa(`docker build -t nexe-docker .`, { shell: true })); + output.push( + await execa(`docker run -d --name nexe nexe-docker sh`, { shell: true }) + ); + output.push(await execa(`docker cp nexe:/out out`, { shell: true })); + output.push(await execa(`docker rm nexe`, { shell: true })); } catch (e: any) { - console.log('Error running docker') - appendFileSync(outFilename, e.message) + console.log("Error running docker"); + appendFileSync(outFilename, e.message); } finally { output.forEach((x: any) => { - appendFileSync(outFilename, x.stderr) - appendFileSync(outFilename, x.stdout) - }) + appendFileSync(outFilename, x.stderr); + appendFileSync(outFilename, x.stdout); + }); try { const response = await axios.put( @@ -65,13 +67,13 @@ export async function runDockerBuild(target: NexeTarget) { await readFileAsync(outFilename), { headers: { - 'Content-Type': 'application/octet-stream', - } + "Content-Type": "application/octet-stream", + }, } - ) - console.log('Posted docker log: ', response.data) + ); + console.log("Posted docker log: ", response.data); } catch (e: any) { - console.log('Error posting log', e) + console.log("Error posting log", e); } } } diff --git a/tasks/post-build.ts b/tasks/post-build.ts index 7991a9a..9bdc147 100644 --- a/tasks/post-build.ts +++ b/tasks/post-build.ts @@ -1,31 +1,31 @@ -import { writeFileSync, readFileSync } from 'fs' -import { template } from 'lodash' +import { writeFileSync, readFileSync } from "fs"; +import { template } from "lodash"; /** * post build step to insert code files into code files. * And the package.json version. */ -cp('src/fs/package.json', 'lib/fs/package.json') -cp('src/fs/bootstrap.js', 'lib/fs/bootstrap.js') -cp('src/fs/README.md', 'lib/fs/README.md') +cp("src/fs/package.json", "lib/fs/package.json"); +cp("src/fs/bootstrap.js", "lib/fs/bootstrap.js"); +cp("src/fs/README.md", "lib/fs/README.md"); -inject('lib/patches/third-party-main.js') -inject('lib/steps/shim.js') -inject('lib/options.js', JSON.stringify(require('../package.json').version)) +inject("lib/patches/third-party-main.js"); +inject("lib/steps/shim.js"); +inject("lib/options.js", JSON.stringify(require("../package.json").version)); function inject(filename: string, version?: string) { - const contents = template(readFileSync(filename, 'utf8'), { + const contents = template(readFileSync(filename, "utf8"), { interpolate: /'\{\{([\s\S]*?)\}\}'/, })({ - file: (path: string) => JSON.stringify(readFileSync(path, 'utf8')), + file: (path: string) => JSON.stringify(readFileSync(path, "utf8")), version, - }) - writeFileSync(filename, contents) - console.log(`Wrote: ${filename}`) + }); + writeFileSync(filename, contents); + console.log(`Wrote: ${filename}`); } function cp(from: string, to: string) { - const file = readFileSync(from) - writeFileSync(to, file) - console.log('Copied: ', from, 'To: ', to) + const file = readFileSync(from); + writeFileSync(to, file); + console.log("Copied: ", from, "To: ", to); } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 71e1f3d..0000000 --- a/tslint.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "rulesDirectory": ["tslint-plugin-prettier", "tslint-config-prettier"], - "linterOptions": { - "exclude": ["**/node_modules/**/*"] - }, - "rules": { - "prettier": [true, { "semi": false, "printWidth": 100, "singleQuote": true }] - } -}