From 272020067470ab658008d1dafebad202571ccfb7 Mon Sep 17 00:00:00 2001 From: Justin Wilaby Date: Sat, 24 May 2025 06:37:14 -0700 Subject: [PATCH] feat: migrated codebase to build both esm and cjs --- .eslintignore | 2 +- .eslintrc.js | 3 + .prettier.mjs | 12 ++ .prettierrc | 4 - mocharc.js | 11 ++ package-lock.json | 247 +++++++++++++++++---------- package.json | 43 ++--- scripts/write-type-package-jsons.mjs | 21 +++ src/api-client.ts | 49 +++--- src/command.ts | 8 +- src/completions.ts | 11 +- src/deps.ts | 62 ------- src/file.ts | 8 +- src/flags/app.ts | 30 ++-- src/flags/index.ts | 14 +- src/flags/org.ts | 6 +- src/flags/pipeline.ts | 6 +- src/flags/team.ts | 16 +- src/git.ts | 4 +- src/index.ts | 15 +- src/login.ts | 8 +- src/particleboard-client.ts | 7 +- src/yubikey.ts | 5 +- test/api-client.test.ts | 2 +- test/command.test.ts | 2 +- test/git.test.ts | 2 +- test/helpers/init.js | 2 +- test/login.test.ts | 6 +- tsconfig.json | 13 +- 29 files changed, 338 insertions(+), 281 deletions(-) create mode 100644 .prettier.mjs delete mode 100644 .prettierrc create mode 100644 mocharc.js create mode 100644 scripts/write-type-package-jsons.mjs delete mode 100644 src/deps.ts diff --git a/.eslintignore b/.eslintignore index 502167f..dc55552 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1 @@ -/lib +/lib \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index a092a82..7a7bd9e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,7 @@ module.exports = { + env: { + mocha: true, + }, extends: [ 'oclif', 'oclif-typescript', diff --git a/.prettier.mjs b/.prettier.mjs new file mode 100644 index 0000000..eceaff0 --- /dev/null +++ b/.prettier.mjs @@ -0,0 +1,12 @@ +const config = { + endOfLine: 'auto', + "singleQuote": true, + "printWidth": 120, + "proseWrap": "always", + "tabWidth": 2, + "useTabs": false, + "trailingComma": "none", + "bracketSpacing": true, + "semi": true +}; +export default config; diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index cd41835..0000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -printWidth: 120 -semi: false -singleQuote: true -trailingComma: "all" diff --git a/mocharc.js b/mocharc.js new file mode 100644 index 0000000..23502be --- /dev/null +++ b/mocharc.js @@ -0,0 +1,11 @@ +module.exports = { + recursive: true, + reporter: 'spec', + require: [ + 'test/helpers/init.js', + 'ts-node/esm', + 'source-map-support/register', + ], + timeout: 360000, + 'watch-extensions': 'ts', +} diff --git a/package-lock.json b/package-lock.json index 252b54e..2a9e205 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,10 @@ "devDependencies": { "@heroku-cli/schema": "^1.0.25", "@types/chai": "^5.2.2", + "@types/debug": "^4.1.12", "@types/inquirer": "^8.2.11", - "@types/mocha": "^10.0.6", - "@types/node": "22.15.17", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.17", "@types/proxyquire": "^1.3.31", "@types/sinon": "^17.0.3", "@types/supports-color": "^5.3.0", @@ -41,15 +42,17 @@ "eslint-config-oclif-typescript": "^3.1.14", "eslint-plugin-import": "^2.31.0", "fancy-test": "^2.0.42", - "mocha": "^10.7.3", + "mocha": "^10.8.2", "nock": "^14.0.1", "np": "^10.2.0", + "prettier": "3.2.4", "proxyquire": "^2.1.3", "sinon": "^20.0.0", "stdout-stderr": "^0.1.13", - "ts-node": "^10.9.1", + "ts-mocha": "^11.1.0", + "ts-node": "^10.9.2", "tslint": "^6.1.3", - "typescript": "^5.7.3" + "typescript": "^5.8.3" }, "engines": { "node": ">= 20" @@ -202,27 +205,6 @@ "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@emnapi/core": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", @@ -838,13 +820,34 @@ } } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@mswjs/interceptors": { "version": "0.37.6", "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.6.tgz", @@ -1144,9 +1147,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, "license": "MIT" }, @@ -1200,6 +1203,16 @@ "@types/deep-eql": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -1257,9 +1270,16 @@ "license": "MIT" }, "node_modules/@types/mocha": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", - "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "dev": true, "license": "MIT" }, @@ -1998,11 +2018,14 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -2137,9 +2160,9 @@ } }, "node_modules/arg": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz", - "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, "license": "MIT" }, @@ -4549,6 +4572,19 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4559,6 +4595,19 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/eslint-plugin-mocha": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz", @@ -7378,16 +7427,18 @@ "license": "ISC" }, "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, + "optional": true, + "peer": true, "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/keyv": { @@ -7964,9 +8015,9 @@ "license": "ISC" }, "node_modules/make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true, "license": "ISC" }, @@ -8110,9 +8161,9 @@ } }, "node_modules/mocha": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", - "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "dev": true, "license": "MIT", "dependencies": { @@ -8152,31 +8203,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, "node_modules/mocha/node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -9439,6 +9465,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/propagate": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", @@ -10923,10 +10965,33 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-mocha": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-11.1.0.tgz", + "integrity": "sha512-yT7FfzNRCu8ZKkYvAOiH01xNma/vLq6Vit7yINKYFNVP8e5UyrYXSOMIipERTpzVKJQ4Qcos5bQo1tNERNZevQ==", + "dev": true, + "license": "MIT", + "bin": { + "ts-mocha": "bin/ts-mocha" + }, + "engines": { + "node": ">= 6.X.X" + }, + "peerDependencies": { + "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X || ^11.X.X", + "ts-node": "^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X", + "tsconfig-paths": "^4.X.X" + }, + "peerDependenciesMeta": { + "tsconfig-paths": { + "optional": true + } + } + }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10968,16 +11033,20 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/tslib": { @@ -11255,9 +11324,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 65eae74..c1eff74 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,10 @@ "devDependencies": { "@heroku-cli/schema": "^1.0.25", "@types/chai": "^5.2.2", + "@types/debug": "^4.1.12", "@types/inquirer": "^8.2.11", - "@types/mocha": "^10.0.6", - "@types/node": "22.15.17", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.17", "@types/proxyquire": "^1.3.31", "@types/sinon": "^17.0.3", "@types/supports-color": "^5.3.0", @@ -37,15 +38,16 @@ "eslint-config-oclif-typescript": "^3.1.14", "eslint-plugin-import": "^2.31.0", "fancy-test": "^2.0.42", - "mocha": "^10.7.3", + "mocha": "^10.8.2", "nock": "^14.0.1", "np": "^10.2.0", + "prettier": "3.2.4", "proxyquire": "^2.1.3", "sinon": "^20.0.0", "stdout-stderr": "^0.1.13", - "ts-node": "^10.9.1", + "ts-mocha": "^11.1.0", "tslint": "^6.1.3", - "typescript": "^5.7.3" + "typescript": "^5.8.3" }, "engines": { "node": ">= 20" @@ -58,27 +60,28 @@ "heroku" ], "license": "ISC", - "main": "lib/index.js", "repository": "heroku/heroku-cli-command", - "mocha": { - "require": [ - "test/helpers/init.js", - "ts-node/register", - "source-map-support/register" - ], - "watch-extensions": "ts", - "recursive": true, - "reporter": "spec", - "timeout": 360000 - }, "scripts": { - "build": "rm -rf lib && tsc", + "build:cjs": "tsc --project ./tsconfig.json --module commonjs --outDir lib/cjs --target esnext", + "build:esm": "tsc --project ./tsconfig.json --module esnext --outDir lib/esm --target esnext", + "build": "rm -rf lib && eslint . --config .eslintrc.js --fix && prettier -w --config ./.prettier.mjs ./src/**/*.ts && (npm run build:cjs & npm run build:esm)", + "postbuild": "node scripts/write-type-package-jsons.mjs", + "pretest": "npm run build", + "test": "export NODE_OPTIONS=\"--loader ts-node/esm\" && mocha 'test/**/*.ts'", "lint": "tsc -p test --noEmit && eslint . --ext .ts", "posttest": "npm run lint", "prepublishOnly": "npm run build && npm run changelog", - "test": "mocha --forbid-only \"test/**/*.test.ts\"", "changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s", "example": "sh examples/run.sh" }, - "types": "./lib/index.d.ts" + "main": "./lib/cjs/index.js", + "module": "./lib/esm/index.js", + "types": "./lib/esm/index.d.ts", + "exports": { + ".": { + "import": "./lib/esm/index.js", + "require": "./lib/cjs/index.js", + "types": "./lib/esm/index.d.ts" + } + } } diff --git a/scripts/write-type-package-jsons.mjs b/scripts/write-type-package-jsons.mjs new file mode 100644 index 0000000..4bfcacf --- /dev/null +++ b/scripts/write-type-package-jsons.mjs @@ -0,0 +1,21 @@ +// This script writes a package.json with the correct "type" field to both lib/esm and lib/cjs +import {existsSync, mkdirSync, writeFileSync} from 'node:fs' +import {join} from 'node:path' + +import pjson from '../package.json' with {type: 'json'} + +const targets = [ + {dir: join(import.meta.dirname, '../lib/esm'), type: 'module'}, + {dir: join(import.meta.dirname, '../lib/cjs'), type: 'commonjs'}, +] + +targets.forEach(({dir, type}) => { + if (!existsSync(dir)) { + mkdirSync(dir, {recursive: true}) + } + + const pkgPath = join(dir, 'package.json') + const pkgContent = JSON.stringify({name: pjson.name, type, version: pjson.version}, null, 2) + '\n' + writeFileSync(pkgPath, pkgContent) + process.stdout.write(`Wrote ${pkgPath}\n`) +}) diff --git a/src/api-client.ts b/src/api-client.ts index 7cdc65b..295a32f 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -1,17 +1,20 @@ import {HTTP, HTTPError, HTTPRequestOptions} from '@heroku/http-call' import {Errors, Interfaces} from '@oclif/core' +import debugModule from 'debug' import inquirer from 'inquirer' -import Netrc from 'netrc-parser' +import {Netrc} from 'netrc-parser' import * as url from 'node:url' -import deps from './deps' -import {Login} from './login' -import {Mutex} from './mutex' -import {IDelinquencyConfig, IDelinquencyInfo, ParticleboardClient} from './particleboard-client' -import {RequestId, requestIdHeader} from './request-id' -import {vars} from './vars' +import {Login} from './login.js' +import {Mutex} from './mutex.js' +import {IDelinquencyConfig, IDelinquencyInfo, ParticleboardClient} from './particleboard-client.js' +import {RequestId, requestIdHeader} from './request-id.js' +import {vars} from './vars.js' +import {yubikey} from './yubikey.js' -const debug = require('debug') +const netrc = new Netrc() + +const debug = debugModule // eslint-disable-next-line @typescript-eslint/no-namespace export namespace APIClient { @@ -59,13 +62,13 @@ export class APIClient { http: typeof HTTP preauthPromises: { [k: string]: Promise> } private _auth?: string - private readonly _login = new Login(this.config, this) + private readonly _login: Login private _particleboard!: ParticleboardClient private _twoFactorMutex: Mutex | undefined constructor(protected config: Interfaces.Config, public options: IOptions = {}) { this.config = config - + this._login = new Login(this.config, this) if (options.required === undefined) options.required = true options.preauth = options.preauth !== false if (options.debug) debug.enable('http') @@ -86,7 +89,7 @@ export class APIClient { protocol: apiUrl.protocol, } const delinquencyConfig: IDelinquencyConfig = {fetch_delinquency: false, warning_shown: false} - this.http = class APIHTTPClient extends deps.HTTP.HTTP.create(opts) { + this.http = class APIHTTPClient extends HTTP.create(opts) { static configDelinquency(url: string, opts: APIClient.Options): void { if (opts.method?.toUpperCase() !== 'GET' || (opts.hostname && opts.hostname !== apiUrl.hostname)) { delinquencyConfig.fetch_delinquency = false @@ -193,7 +196,7 @@ export class APIClient { this.showWarnings(response) return response } catch (error) { - if (!(error instanceof deps.HTTP.HTTPError)) throw error + if (!(error instanceof HTTPError)) throw error if (retries > 0) { if (opts.retryAuth !== false && error.http.statusCode === 401 && error.body.id === 'unauthorized') { if (process.env.HEROKU_API_KEY) { @@ -258,11 +261,11 @@ export class APIClient { get auth(): string | undefined { if (!this._auth) { - if (process.env.HEROKU_API_TOKEN && !process.env.HEROKU_API_KEY) deps.cli.warn('HEROKU_API_TOKEN is set but you probably meant HEROKU_API_KEY') + if (process.env.HEROKU_API_TOKEN && !process.env.HEROKU_API_KEY) Errors.warn('HEROKU_API_TOKEN is set but you probably meant HEROKU_API_KEY') this._auth = process.env.HEROKU_API_KEY if (!this._auth) { - deps.netrc.loadSync() - this._auth = deps.netrc.machines[vars.apiHost] && deps.netrc.machines[vars.apiHost].password + netrc.loadSync() + this._auth = netrc.machines[vars.apiHost] && netrc.machines[vars.apiHost].password } } @@ -280,13 +283,13 @@ export class APIClient { get particleboard(): ParticleboardClient { if (this._particleboard) return this._particleboard - this._particleboard = new deps.ParticleboardClient(this.config) + this._particleboard = new ParticleboardClient(this.config) return this._particleboard } get twoFactorMutex(): Mutex { if (!this._twoFactorMutex) { - this._twoFactorMutex = new deps.Mutex() + this._twoFactorMutex = new Mutex() } return this._twoFactorMutex @@ -311,9 +314,9 @@ export class APIClient { if (error instanceof Errors.CLIError) Errors.warn(error) } - delete Netrc.machines['api.heroku.com'] - delete Netrc.machines['git.heroku.com'] - await Netrc.save() + delete netrc.machines['api.heroku.com'] + delete netrc.machines['git.heroku.com'] + await netrc.save() } patch(url: string, options: APIClient.Options = {}) { @@ -343,7 +346,7 @@ export class APIClient { } twoFactorPrompt() { - deps.yubikey.enable() + yubikey.enable() return this.twoFactorMutex.synchronize(async () => { try { const {factor} = await inquirer.prompt([{ @@ -352,10 +355,10 @@ export class APIClient { name: 'factor', type: 'password', }]) - deps.yubikey.disable() + yubikey.disable() return factor } catch (error) { - deps.yubikey.disable() + yubikey.disable() throw error } }) diff --git a/src/command.ts b/src/command.ts index b1c2f80..cde5e4d 100644 --- a/src/command.ts +++ b/src/command.ts @@ -9,14 +9,10 @@ import {NonExistentFlagsError} from '@oclif/core/lib/parser/errors' import parser from 'yargs-parser' import unparser from 'yargs-unparser' -const pjson = require('../package.json') - -import {APIClient, IOptions} from './api-client' -import deps from './deps' +import {APIClient, IOptions} from './api-client.js' export abstract class Command extends Base { allowArbitraryFlags: boolean = false - base = `${pjson.name}@${pjson.version}` _heroku!: APIClient get heroku(): APIClient { @@ -25,7 +21,7 @@ export abstract class Command extends Base { debug: process.env.HEROKU_DEBUG === '1' || process.env.HEROKU_DEBUG?.toUpperCase() === 'TRUE', debugHeaders: process.env.HEROKU_DEBUG_HEADERS === '1' || process.env.HEROKU_DEBUG_HEADERS?.toUpperCase() === 'TRUE', } - this._heroku = new deps.APIClient(this.config, options) + this._heroku = new APIClient(this.config, options) return this._heroku } diff --git a/src/completions.ts b/src/completions.ts index f053c80..23d6aca 100644 --- a/src/completions.ts +++ b/src/completions.ts @@ -1,13 +1,14 @@ import {Errors, Interfaces} from '@oclif/core' +import {readFile, readdir} from 'node:fs/promises' import * as path from 'node:path' -import deps from './deps' -import {configRemote, getGitRemotes} from './git' +import {APIClient} from './api-client.js' +import {configRemote, getGitRemotes} from './git.js' export const oneDay = 60 * 60 * 24 export const herokuGet = async (resource: string, ctx: {config: Interfaces.Config}): Promise => { - const heroku = new deps.APIClient(ctx.config) + const heroku = new APIClient(ctx.config) let {body: resources} = await heroku.get(`/${resource}`) if (typeof resources === 'string') resources = JSON.parse(resources) return resources.map((a: any) => a.name).sort() @@ -71,7 +72,7 @@ export const DynoSizeCompletion = { export const FileCompletion = { async options() { - const files = await deps.file.readdir(process.cwd()) + const files = await readdir(process.cwd()) return files }, @@ -91,7 +92,7 @@ export const ProcessTypeCompletion = { let types: string[] = [] const procfile = path.join(process.cwd(), 'Procfile') try { - const buff = await deps.file.readFile(procfile) + const buff = await readFile(procfile) types = buff .toString() .split('\n') diff --git a/src/deps.ts b/src/deps.ts deleted file mode 100644 index 300e935..0000000 --- a/src/deps.ts +++ /dev/null @@ -1,62 +0,0 @@ -// remote -import apiClient = require('./api-client') -import file = require('./file') -import flags = require('./flags') -import git = require('./git') -import mutex = require('./mutex') -import particleboardClient = require('./particleboard-client') -import yubikey = require('./yubikey') -import HTTP = require('@heroku/http-call') -import oclif = require('@oclif/core') -import netrc = require('netrc-parser') - -const {ux} = oclif - -export const deps = { - get APIClient(): typeof apiClient.APIClient { - return fetch('./api-client').APIClient - }, - get Git(): typeof git.Git { - return fetch('./git').Git - }, - get HTTP(): typeof HTTP { - return fetch('@heroku/http-call') - }, - - // local - get Mutex(): typeof mutex.Mutex { - return fetch('./mutex').Mutex - }, - get ParticleboardClient(): typeof particleboardClient.ParticleboardClient { - return fetch('./particleboard-client').ParticleboardClient - }, - // remote - get cli(): typeof ux { - return fetch('@oclif/core').ux - }, - get file(): typeof file { - return fetch('./file') - }, - get flags(): typeof flags { - return fetch('./flags') - }, - get netrc(): typeof netrc.default { - return fetch('netrc-parser').default - }, - get yubikey(): typeof yubikey.yubikey { - return fetch('./yubikey').yubikey - }, -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const cache: Record = {} - -function fetch(s: string) { - if (!cache[s]) { - cache[s] = require(s) - } - - return cache[s] -} - -export default deps diff --git a/src/file.ts b/src/file.ts index 356c80a..5360362 100644 --- a/src/file.ts +++ b/src/file.ts @@ -1,14 +1,14 @@ -import * as fs from 'fs' -import {promisify} from 'util' +import debugModule from 'debug' +import * as fs from 'node:fs' +import {promisify} from 'node:util' let _debug: any function debug(...args: any[]) { - if (_debug) _debug = require('debug')('@heroku-cli/command:file') + if (!_debug) _debug = debugModule('@heroku-cli/command:file') _debug(...args) } export function exists(f: string): Promise { - // eslint-disable-next-line n/no-deprecated-api return promisify(fs.exists)(f) } diff --git a/src/flags/app.ts b/src/flags/app.ts index 013a490..93cabdf 100644 --- a/src/flags/app.ts +++ b/src/flags/app.ts @@ -1,6 +1,6 @@ -import {Errors, Flags} from '@oclif/core' +import { Errors, Flags } from '@oclif/core'; -import {IGitRemotes, configRemote, getGitRemotes} from '../git' +import { IGitRemotes, configRemote, getGitRemotes } from '../git.js'; class MultipleRemotesError extends Errors.CLIError { constructor(gitRemotes: IGitRemotes[]) { @@ -11,31 +11,31 @@ class MultipleRemotesError extends Errors.CLIError { Because of this, we can't determine which app you want to run this command against. Specify the app you want with --app or --remote. Heroku remotes in repo: - ${gitRemotes.map(r => `${r.app} (${r.remote})`).join('\n')} + ${gitRemotes.map((r) => `${r.app} (${r.remote})`).join('\n')} - https://devcenter.heroku.com/articles/multiple-environments`) + https://devcenter.heroku.com/articles/multiple-environments`); } } export const app = Flags.custom({ char: 'a', - async default({flags, options}) { - const envApp = process.env.HEROKU_APP - if (envApp) return envApp - const gitRemotes = getGitRemotes(flags.remote || configRemote()) - if (gitRemotes.length === 1) return gitRemotes[0].app + async default({ flags, options }) { + const envApp = process.env.HEROKU_APP; + if (envApp) return envApp; + const gitRemotes = getGitRemotes(flags.remote || configRemote()); + if (gitRemotes.length === 1) return gitRemotes[0].app; if (flags.remote && gitRemotes.length === 0) { - Errors.error(`remote ${flags.remote} not found in git remotes`) + Errors.error(`remote ${flags.remote} not found in git remotes`); } if (gitRemotes.length > 1 && options.required) { - throw new MultipleRemotesError(gitRemotes) + throw new MultipleRemotesError(gitRemotes); } }, - description: 'app to run command against', -}) + description: 'app to run command against' +}); export const remote = Flags.custom({ char: 'r', - description: 'git remote of app to use', -}) + description: 'git remote of app to use' +}); diff --git a/src/flags/index.ts b/src/flags/index.ts index fb99554..e1fbd1f 100644 --- a/src/flags/index.ts +++ b/src/flags/index.ts @@ -1,11 +1,11 @@ -import {Flags} from '@oclif/core' +import { Flags } from '@oclif/core'; -export {app, remote} from './app' -export {org} from './org' -export {pipeline} from './pipeline' -export {team} from './team' +export { app, remote } from './app.js'; +export { org } from './org.js'; +export { pipeline } from './pipeline.js'; +export { team } from './team.js'; // Explicitly export oclif flag types using object destructuring, sorted alphabetically -export const {boolean, custom, directory, file, integer, option, string, url} = Flags +export const { boolean, custom, directory, file, integer, option, string, url } = Flags; -export {Flags} from '@oclif/core' +export { Flags } from '@oclif/core'; diff --git a/src/flags/org.ts b/src/flags/org.ts index 44f8b59..b8cee71 100644 --- a/src/flags/org.ts +++ b/src/flags/org.ts @@ -1,8 +1,8 @@ -import {Flags} from '@oclif/core' +import { Flags } from '@oclif/core'; export const org = Flags.custom({ char: 'o', default: () => process.env.HEROKU_ORGANIZATION, description: 'name of org', - hidden: true, -}) + hidden: true +}); diff --git a/src/flags/pipeline.ts b/src/flags/pipeline.ts index fa48ca7..6a76ee9 100644 --- a/src/flags/pipeline.ts +++ b/src/flags/pipeline.ts @@ -1,6 +1,6 @@ -import {Flags} from '@oclif/core' +import { Flags } from '@oclif/core'; export const pipeline = Flags.custom({ char: 'p', - description: 'name of pipeline', -}) + description: 'name of pipeline' +}); diff --git a/src/flags/team.ts b/src/flags/team.ts index 280332a..baceb27 100644 --- a/src/flags/team.ts +++ b/src/flags/team.ts @@ -1,12 +1,12 @@ -import {Flags} from '@oclif/core' +import { Flags } from '@oclif/core'; export const team = Flags.custom({ char: 't', - async default({flags}) { - const {HEROKU_ORGANIZATION: org, HEROKU_TEAM: team} = process.env - if (flags.org) return flags.org - if (team) return team - if (org) return org + async default({ flags }) { + const { HEROKU_ORGANIZATION: org, HEROKU_TEAM: team } = process.env; + if (flags.org) return flags.org; + if (team) return team; + if (org) return org; }, - description: 'team to use', -}) + description: 'team to use' +}); diff --git a/src/git.ts b/src/git.ts index ee7154f..7895266 100644 --- a/src/git.ts +++ b/src/git.ts @@ -1,6 +1,7 @@ import {Errors} from '@oclif/core' +import {execSync as exec} from 'node:child_process' -import {vars} from './vars' +import {vars} from './vars.js' export interface IGitRemote { name: string @@ -19,7 +20,6 @@ export class Git { } exec(cmd: string): string { - const {execSync: exec} = require('child_process') try { return exec(`git ${cmd}`, { encoding: 'utf8', diff --git a/src/index.ts b/src/index.ts index 0dd05a0..bd91523 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,9 @@ - -export {APIClient} from './api-client' -export {Command, Command as default} from './command' -export * as completions from './completions' -export * as flags from './flags' -export {vars} from './vars' +export * from './api-client.js' +export {Command, Command as default} from './command.js' +export * from './completions.js' +export * as flags from './flags/index.js' +export * from './git.js' +export * from './mutex.js' +export * from './particleboard-client.js' +export * from './vars.js' +export * from './yubikey.js' diff --git a/src/login.ts b/src/login.ts index dc38969..8e52b5a 100644 --- a/src/login.ts +++ b/src/login.ts @@ -4,16 +4,16 @@ import HTTP from '@heroku/http-call' import color from '@heroku-cli/color' import * as Heroku from '@heroku-cli/schema' import {Interfaces, ux} from '@oclif/core' +import herokuDebug from 'debug' import inquirer, {QuestionCollection} from 'inquirer' import PressToContinuePrompt from 'inquirer-press-to-continue' import Netrc from 'netrc-parser' import * as os from 'node:os' import open from 'open' -import {APIClient, HerokuAPIError} from './api-client' -import {vars} from './vars' - -const debug = require('debug')('heroku-cli-command') +import {APIClient, HerokuAPIError} from './api-client.js' +import {vars} from './vars.js' +const debug = herokuDebug.default('heroku-cli-command') const hostname = os.hostname() const thirtyDays = 60 * 60 * 24 * 30 inquirer.registerPrompt('press-to-continue', PressToContinuePrompt) diff --git a/src/particleboard-client.ts b/src/particleboard-client.ts index f85681b..f53448e 100644 --- a/src/particleboard-client.ts +++ b/src/particleboard-client.ts @@ -2,9 +2,8 @@ import {HTTP, HTTPRequestOptions} from '@heroku/http-call' import {Interfaces} from '@oclif/core' import * as url from 'node:url' -import deps from './deps' -import {RequestId, requestIdHeader} from './request-id' -import {vars} from './vars' +import {RequestId, requestIdHeader} from './request-id.js' +import {vars} from './vars.js' export interface IDelinquencyInfo { scheduled_deletion_time?: null | string @@ -37,7 +36,7 @@ export class ParticleboardClient { port: particleboardUrl.port, protocol: particleboardUrl.protocol, } - this.http = class ParticleboardHTTPClient extends deps.HTTP.HTTP.create(particleboardOpts) { + this.http = class ParticleboardHTTPClient extends HTTP.create(particleboardOpts) { static async request(url: string, opts: HTTPRequestOptions = {}): Promise> { opts.headers = opts.headers || {} opts.headers[requestIdHeader] = RequestId.create() && RequestId.headerValue diff --git a/src/yubikey.ts b/src/yubikey.ts index 36da296..9f71231 100644 --- a/src/yubikey.ts +++ b/src/yubikey.ts @@ -1,8 +1,9 @@ +import {execSync} from 'node:child_process' + function toggle(onoff: string) { - const cp = require('child_process') if (yubikey.platform !== 'darwin') return try { - cp.execSync( + execSync( `osascript -e 'if application "yubiswitch" is running then tell application "yubiswitch" to ${onoff}'`, {stdio: 'inherit'}, ) diff --git a/test/api-client.test.ts b/test/api-client.test.ts index f530440..1b22a0d 100644 --- a/test/api-client.test.ts +++ b/test/api-client.test.ts @@ -1,7 +1,7 @@ import {Config} from '@oclif/core' import base, {expect} from 'fancy-test' import nock from 'nock' -import {resolve} from 'path' +import {resolve} from 'node:path' import * as sinon from 'sinon' import {stderr} from 'stdout-stderr' diff --git a/test/command.test.ts b/test/command.test.ts index 07d0ce3..40cc966 100644 --- a/test/command.test.ts +++ b/test/command.test.ts @@ -1,6 +1,6 @@ import {Config} from '@oclif/core' import base, {expect} from 'fancy-test' -import {resolve} from 'path' +import {resolve} from 'node:path' import {Command} from '../src/command' import * as flags from '../src/flags' diff --git a/test/git.test.ts b/test/git.test.ts index a7c4397..bc5fdbe 100644 --- a/test/git.test.ts +++ b/test/git.test.ts @@ -1,5 +1,5 @@ -import childProcess from 'child_process' import {expect, fancy} from 'fancy-test' +import childProcess from 'node:child_process' import {Git} from '../src/git' diff --git a/test/helpers/init.js b/test/helpers/init.js index f8e35e6..f97148b 100644 --- a/test/helpers/init.js +++ b/test/helpers/init.js @@ -1,2 +1,2 @@ -const path = require('path') +const path = require('node:path') process.env.TS_NODE_PROJECT = path.resolve('test/tsconfig.json') diff --git a/test/login.test.ts b/test/login.test.ts index 763e45a..5d4e6ca 100644 --- a/test/login.test.ts +++ b/test/login.test.ts @@ -1,12 +1,12 @@ import {Config} from '@oclif/core' import base, {expect} from 'fancy-test' -import inquirer from 'inquirer' +import * as inquirer from 'inquirer' import Netrc from 'netrc-parser' import nock from 'nock' -import {resolve} from 'path' +import {resolve} from 'node:path' import * as sinon from 'sinon' -import {Command as CommandBase} from '../src/command' +import {Command as CommandBase} from '../src/command.js' class Command extends CommandBase { async run() {} diff --git a/tsconfig.json b/tsconfig.json index f5e77f4..20b1bff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,17 +4,18 @@ "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "importHelpers": true, - "module": "commonjs", + "module": "esnext", + "moduleResolution": "node", "outDir": "./lib", "pretty": true, - "rootDirs": [ - "./src" - ], + "rootDir": "./src", + "baseUrl": "./", "skipLibCheck": true, "strict": true, - "target": "es2017" + "target": "ES2020", + "resolveJsonModule": true }, "include": [ - "./src/**/*" + "src/**/*" ] }