diff --git a/.github/renovate.json b/.github/renovate.json index 6bd88fb..0aa24cb 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,4 +1,4 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["github>hypermodeinc/renovate-config"] + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["github>hypermodeinc/renovate-config"] } diff --git a/.trunk/configs/.markdownlint.json b/.trunk/configs/.markdownlint.json index 449148d..469f446 100644 --- a/.trunk/configs/.markdownlint.json +++ b/.trunk/configs/.markdownlint.json @@ -1,8 +1,8 @@ { - "line-length": { "line_length": 150, "tables": false }, - "no-inline-html": false, - "no-bare-urls": false, - "no-space-in-emphasis": false, - "no-emphasis-as-heading": false, - "first-line-heading": false + "line-length": { "line_length": 150, "tables": false }, + "no-inline-html": false, + "no-bare-urls": false, + "no-space-in-emphasis": false, + "no-emphasis-as-heading": false, + "first-line-heading": false } diff --git a/.trunk/configs/cspell.json b/.trunk/configs/cspell.json index 7e69bee..dcb2314 100644 --- a/.trunk/configs/cspell.json +++ b/.trunk/configs/cspell.json @@ -1,18 +1,18 @@ { - "version": "0.2", - "language": "en", - "words": [ - "acifani", - "commandsstop", - "Hypermode", - "hypermodeinc", - "oclif", - "pjson", - "postpack", - "sindresorhus", - "tinygo", - "tocstop", - "tseslint", - "usagestop" - ] + "version": "0.2", + "language": "en", + "words": [ + "acifani", + "commandsstop", + "Hypermode", + "hypermodeinc", + "oclif", + "pjson", + "postpack", + "sindresorhus", + "tinygo", + "tocstop", + "tseslint", + "usagestop" + ] } diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 371fe0d..a4ff825 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -2,7 +2,7 @@ # To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml version: 0.1 cli: - version: 1.22.11 + version: 1.22.12 # Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins) plugins: sources: @@ -17,19 +17,29 @@ runtimes: - python@3.10.8 # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) lint: + ignore: + - linters: [prettier] + paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" + - "**/*.css" + - "**/*.html" + - "**/*.json" enabled: - trivy@0.61.0 - actionlint@1.7.7 - - checkov@3.2.394 - - eslint@9.23.0 + - checkov@3.2.396 - git-diff-check - markdownlint@0.44.0 - - osv-scanner@2.0.0 + - osv-scanner@2.0.1 - prettier@3.5.3 - - renovate@39.219.3 + - biome@1.9.4 + - renovate@39.233.2 - shellcheck@0.10.0 - shfmt@3.6.0 - - trufflehog@3.88.20 + - trufflehog@3.88.22 - yamllint@1.37.0 actions: enabled: diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 29d4338..8b89261 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["trunk.io"] + "recommendations": ["trunk.io"] } diff --git a/.vscode/launch.json b/.vscode/launch.json index b4ac0da..de687e0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,22 +1,26 @@ { - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "attach", - "name": "Attach", - "port": 9229, - "skipFiles": ["/**"] - }, - { - "type": "node", - "request": "launch", - "name": "Execute Command", - "skipFiles": ["/**"], - "runtimeExecutable": "node", - "runtimeArgs": ["--loader", "ts-node/esm", "--no-warnings=ExperimentalWarning"], - "program": "${workspaceFolder}/bin/dev.js", - "args": ["hello", "world"] - } - ] + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "name": "Attach", + "port": 9229, + "skipFiles": ["/**"] + }, + { + "type": "node", + "request": "launch", + "name": "Execute Command", + "skipFiles": ["/**"], + "runtimeExecutable": "node", + "runtimeArgs": [ + "--loader", + "ts-node/esm", + "--no-warnings=ExperimentalWarning" + ], + "program": "${workspaceFolder}/bin/dev.js", + "args": ["hello", "world"] + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1e49ba9..ae7708c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,9 @@ { - "editor.formatOnSave": true, - "editor.defaultFormatter": "trunk.io", - "editor.trimAutoWhitespace": true, - "trunk.autoInit": false, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - } + "editor.formatOnSave": true, + "editor.defaultFormatter": "trunk.io", + "editor.trimAutoWhitespace": true, + "trunk.autoInit": false, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/README.md b/README.md index 32bb605..65295a2 100644 --- a/README.md +++ b/README.md @@ -45,5 +45,5 @@ hyp link ## License -Hyp CLI is © Hypermode Inc., and licensed under the terms of the Apache License, -Version 2.0. See the [LICENSE](./LICENSE) file for a complete copy of the license. +Hyp CLI is © Hypermode Inc., and licensed under the terms of the Apache License, Version 2.0. See +the [LICENSE](./LICENSE) file for a complete copy of the license. diff --git a/bin/dev.js b/bin/dev.js index 6f1e0af..0c3a40e 100755 --- a/bin/dev.js +++ b/bin/dev.js @@ -1,5 +1,5 @@ #!/usr/bin/env -S node --loader ts-node/esm --no-warnings --disable-warning=ExperimentalWarning -import { execute } from "@oclif/core" +import { execute } from "@oclif/core"; -await execute({ development: true, dir: import.meta.url }) +await execute({ development: true, dir: import.meta.url }); diff --git a/bin/run.js b/bin/run.js index 4a39c5c..94a0d6f 100755 --- a/bin/run.js +++ b/bin/run.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { execute } from "@oclif/core" +import { execute } from "@oclif/core"; -await execute({ dir: import.meta.url }) +await execute({ dir: import.meta.url }); diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 2184230..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check - -import eslint from "@eslint/js" -import tseslint from "typescript-eslint" - -export default tseslint.config({ - extends: [eslint.configs.recommended, ...tseslint.configs.recommended], - - ignores: ["node_modules/**", "dist/**"], - rules: { - "no-undef": "off", - "@typescript-eslint/no-explicit-any": "off", - }, -}) diff --git a/package-lock.json b/package-lock.json index 5e267f6..0ad25ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,17 +20,12 @@ "hyp": "bin/run.js" }, "devDependencies": { - "@eslint/js": "9.21.0", "@oclif/test": "4.1.11", - "@types/eslint__js": "8.42.3", "@types/node": "22.13.5", - "@typescript-eslint/eslint-plugin": "8.24.1", - "eslint": "9.21.0", "oclif": "4.17.31", "prettier": "3.5.2", "ts-node": "10.9.2", - "typescript": "5.7.3", - "typescript-eslint": "8.24.1" + "typescript": "5.7.3" } }, "node_modules/@aws-crypto/crc32": { @@ -997,248 +992,6 @@ "node": ">=12" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "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/eslint-utils/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": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", - "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.12.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "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/retry": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@inquirer/checkbox": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.4.tgz", @@ -2620,34 +2373,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint__js": { - "version": "8.42.3", - "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", - "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", @@ -2655,13 +2380,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/mute-stream": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", @@ -2695,186 +2413,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz", - "integrity": "sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/type-utils": "8.24.1", - "@typescript-eslint/utils": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.1.tgz", - "integrity": "sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/typescript-estree": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz", - "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz", - "integrity": "sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.24.1", - "@typescript-eslint/utils": "8.24.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz", - "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz", - "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz", - "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/typescript-estree": "8.24.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz", - "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.24.1", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -2888,16 +2426,6 @@ "node": ">=0.4.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", @@ -2911,23 +2439,6 @@ "node": ">=0.4.0" } }, - "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/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2983,13 +2494,6 @@ "dev": true, "license": "MIT" }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -3093,16 +2597,6 @@ "node": ">=14.16" } }, - "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/camel-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", @@ -3277,21 +2771,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -3338,13 +2817,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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/default-browser": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", @@ -3494,227 +2966,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", - "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/core": "^0.12.0", - "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.21.0", - "@eslint/plugin-kit": "^0.2.7", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.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/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/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "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": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.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/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "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/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/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -3729,13 +2980,6 @@ "node": ">=4" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -3764,13 +3008,6 @@ "node": ">= 6" } }, - "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": "3.0.0", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", @@ -3823,19 +3060,6 @@ "reusify": "^1.0.4" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -3869,23 +3093,6 @@ "node": ">=8" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -3896,27 +3103,6 @@ "micromatch": "^4.0.2" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" - }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -3994,32 +3180,6 @@ "dev": true, "license": "ISC" }, - "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/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "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", @@ -4086,13 +3246,6 @@ "node": ">=14" } }, - "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": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4186,33 +3339,6 @@ "node": ">= 4" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "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/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/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -4371,13 +3497,6 @@ "node": ">=8" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -4446,19 +3565,6 @@ "node": ">=8" } }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "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", @@ -4473,20 +3579,6 @@ "dev": true, "license": "MIT" }, - "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/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/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -4507,20 +3599,6 @@ "json-buffer": "3.0.1" } }, - "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", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -4533,22 +3611,6 @@ "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -4556,13 +3618,6 @@ "dev": true, "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/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -4665,13 +3720,6 @@ "node": "^18.17.0 || >=20.5.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/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -4918,31 +3966,6 @@ "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/optionator/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/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -4962,38 +3985,6 @@ "node": ">=12.20" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -5005,19 +3996,6 @@ "tslib": "^2.0.3" } }, - "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/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -5054,26 +4032,6 @@ "tslib": "^2.0.3" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5095,16 +4053,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "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": "3.5.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", @@ -5128,16 +4076,6 @@ "dev": true, "license": "ISC" }, - "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", @@ -5191,16 +4129,6 @@ "dev": true, "license": "MIT" }, - "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/responselike": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", @@ -5323,29 +4251,6 @@ "upper-case-first": "^2.0.2" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -5467,19 +4372,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -5590,19 +4482,6 @@ "node": ">=8.0" } }, - "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -5667,19 +4546,6 @@ "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-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -5706,29 +4572,6 @@ "node": ">=14.17" } }, - "node_modules/typescript-eslint": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.24.1.tgz", - "integrity": "sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.24.1", - "@typescript-eslint/parser": "8.24.1", - "@typescript-eslint/utils": "8.24.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", @@ -5766,16 +4609,6 @@ "tslib": "^2.0.3" } }, - "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/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -5818,22 +4651,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -5846,16 +4663,6 @@ "node": ">=8" } }, - "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/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -5886,19 +4693,6 @@ "node": ">=6" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yoctocolors-cjs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", diff --git a/package.json b/package.json index fc5c4c3..84066cb 100644 --- a/package.json +++ b/package.json @@ -1,75 +1,60 @@ { - "name": "@hypermode/hyp-cli", - "description": "The Hypermode CLI", - "version": "", - "author": "Hypermode Inc.", - "license": "Apache-2.0", - "homepage": "https://hypermode.com", - "bin": { - "hyp": "./bin/run.js" - }, - "repository": "github:hypermodeinc/hyp-cli", - "bugs": "https://github.com/hypermodeinc/hyp-cli/issues", - "dependencies": { - "@inquirer/core": "10.1.9", - "@inquirer/prompts": "7.4.0", - "@oclif/core": "4.2.10", - "@scarf/scarf": "1.4.0", - "@sindresorhus/slugify": "2.2.1", - "chalk": "5.4.1", - "gradient-string": "3.0.0", - "open": "10.1.0" - }, - "devDependencies": { - "@eslint/js": "9.21.0", - "@oclif/test": "4.1.11", - "@types/eslint__js": "8.42.3", - "@typescript-eslint/eslint-plugin": "8.24.1", - "@types/node": "22.13.5", - "eslint": "9.21.0", - "oclif": "4.17.31", - "prettier": "3.5.2", - "ts-node": "10.9.2", - "typescript": "5.7.3", - "typescript-eslint": "8.24.1" - }, - "files": [ - "/bin", - "/dist", - "/oclif.manifest.json" - ], - "keywords": [ - "Hypermode", - "Modus", - "CLI" - ], - "main": "dist/index.js", - "types": "dist/index.d.ts", - "type": "module", - "oclif": { - "bin": "hyp", - "dirname": "hyp", - "helpClass": "./dist/custom/help", - "commands": "./dist/commands", - "plugins": [], - "topicSeparator": " ", - "topics": { - "org": { - "description": "Manage your Hypermode organization" - } - } - }, - "scripts": { - "lint": "eslint .", - "pretty": "prettier --write .", - "pretty:check": "prettier --check .", - "pack": "npm pack", - "build": "rm -rf dist && tsc -b", - "watch": "rm -rf dist && tsc -b -w", - "postpack": "rm -f oclif.manifest.json", - "prepack": "npm i && npm run build && oclif manifest" - }, - "scarfSettings": { - "allowTopLevel": true - } + "name": "@hypermode/hyp-cli", + "description": "The Hypermode CLI", + "version": "", + "author": "Hypermode Inc.", + "license": "Apache-2.0", + "homepage": "https://hypermode.com", + "bin": { + "hyp": "./bin/run.js" + }, + "repository": "github:hypermodeinc/hyp-cli", + "bugs": "https://github.com/hypermodeinc/hyp-cli/issues", + "dependencies": { + "@inquirer/core": "10.1.9", + "@inquirer/prompts": "7.4.0", + "@oclif/core": "4.2.10", + "@scarf/scarf": "1.4.0", + "@sindresorhus/slugify": "2.2.1", + "chalk": "5.4.1", + "gradient-string": "3.0.0", + "open": "10.1.0" + }, + "devDependencies": { + "@oclif/test": "4.1.11", + "@types/node": "22.13.5", + "oclif": "4.17.31", + "prettier": "3.5.2", + "ts-node": "10.9.2", + "typescript": "5.7.3" + }, + "files": ["/bin", "/dist", "/oclif.manifest.json"], + "keywords": ["Hypermode", "CLI"], + "main": "dist/index.js", + "types": "dist/index.d.ts", + "type": "module", + "oclif": { + "bin": "hyp", + "dirname": "hyp", + "helpClass": "./dist/custom/help", + "commands": "./dist/commands", + "plugins": [], + "topicSeparator": " ", + "topics": { + "org": { + "description": "Manage your Hypermode organization" + } + } + }, + "scripts": { + "lint": "trunk check", + "pack": "npm pack", + "build": "rm -rf dist && tsc -b", + "watch": "rm -rf dist && tsc -b -w", + "postpack": "rm -f oclif.manifest.json", + "prepack": "npm i && npm run build && oclif manifest" + }, + "scarfSettings": { + "allowTopLevel": true + } } diff --git a/src/commands/link/index.ts b/src/commands/link/index.ts index 21aaca6..6a4b62d 100644 --- a/src/commands/link/index.ts +++ b/src/commands/link/index.ts @@ -3,231 +3,232 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Command } from "@oclif/core"; import * as http from "node:http"; import { URL } from "node:url"; +import { Command } from "@oclif/core"; import open from "open"; export default class LinkIndex extends Command { - static override hidden = true; - - static override args = {}; - - // static override description = "Link a repo with a Modus App to a Hypermode Project"; - static override description = "Temporarily disabled during migration"; - - static override examples = ["<%= config.bin %> <%= command.id %>"]; - - static override flags = {}; - - public async getUserInstallationThroughAuthFlow(): Promise { - return new Promise((resolve, reject) => { - const server = http.createServer(async (req, res) => { - try { - const url = new URL(req.url ?? "", `http://${req.headers.host}`); - const installationId = url.searchParams.get("install_id"); - - if (!installationId) { - res.writeHead(400, { "Content-Type": "text/plain" }); - res.end("Installation ID not found in the request."); - return; - } - - res.writeHead(200, { "Content-Type": "text/html" }); - res.end(linkHTML); - - // Close all existing connections - server.closeAllConnections(); - - // Close the server and wait for it to actually close - server.close(async (err) => { - if (err) { - reject(err); - return; - } - - resolve(installationId); - }); - } catch (error) { - res.writeHead(500, { "Content-Type": "text/plain" }); - res.end("An error occurred during authentication."); - reject(error); - } - }); - - // Set a timeout for the server - const timeoutDuration = 300_000; // 300 seconds in milliseconds - const timeout = setTimeout(() => { - server.closeAllConnections(); - server.close(); - reject(new Error("Authentication timed out. Please try again.")); - }, timeoutDuration); - - // Listen on port 5051 for the redirect - server.listen(5051, "localhost", async () => { - try { - this.log("Opening link page..."); - await this.openLinkPage(); - } catch (error) { - server.close(); - reject(error); - } - }); - - // Ensure the timeout is cleared if the server closes successfully - server.on("close", () => { - clearTimeout(timeout); - }); - - // Handle server errors - server.on("error", (error) => { - clearTimeout(timeout); - reject(error); - }); - }); - } - - public async openLinkPage() { - // Open the Hypermode sign-in page in the default browser - const state = encodeURIComponent(JSON.stringify({ p: 5051, s: "cli" })); - const linkUrl = "https://github.com/apps/hypermode/installations/new?state=" + state; - await open(linkUrl); - } - - public async run(): Promise { - this.error("Temporarily disabled during migration"); - return; - - // // check if the directory has a .git/config with a remote named 'origin', if not, throw an error and ask them to set that up - // const gitConfigFilePath = getGitConfigFilePath(); - - // if (!(await fileExists(gitConfigFilePath))) { - // throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); - // } - - // // Check if the current branch is 'main' - // let currentBranch = ""; - // try { - // currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); - // } catch (error) { - // this.log(chalk.red("Unable to determine the current branch.")); - // throw error; - // } - - // if (currentBranch !== "main") { - // this.log(chalk.red("You must be on the 'main' branch to link your repository.")); - // this.log("Please switch to the 'main' branch:"); - // this.log(` > ${chalk.blue("git checkout main")}`); - // this.log("or rename your current branch to 'main'."); - // this.log(` > ${chalk.blue("git branch -m main")}`); - // this.exit(1); - // } - - // const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); - - // if (!remoteUrl) { - // this.log(chalk.red("`hyp link` requires a git remote to work")); - // const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); - // const projectName = path.basename(gitRoot); - // this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); - // this.log(`And push your code:`); - // this.log(` > ${chalk.blue("git remote add origin )")}`); - // this.log(` > ${chalk.blue("git push -u origin main")}`); - - // this.exit(1); - // } - - // // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, - // // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json - - // const settingsFilePath = getSettingsFilePath(); - // if (!(await fileExists(settingsFilePath))) { - // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - // return; - // } - - // const settings = await readSettingsJson(settingsFilePath); - - // if (!settings.email || !settings.apiKey || !settings.orgId) { - // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - // return; - // } - - // const { gitOwner, repoName } = parseGitUrl(remoteUrl); - - // const repoFullName = `${gitOwner}/${repoName}`; - - // let installationId = null; - - // if (!settings.installationIds || !settings.installationIds[gitOwner]) { - // installationId = await this.getUserInstallationThroughAuthFlow(); - // await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); - // } else { - // installationId = settings.installationIds[gitOwner]; - // } - - // // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error - // const repoId = await sendGetRepoIdReq(settings.apiKey, installationId, remoteUrl); - - // if (!repoId) { - // throw new Error("No repoId found for the given installationId and gitUrl"); - // } - - // // get list of the projects for the user in this org, if any have no repoId, ask if they want to link it, or give option of none. - // // If they pick an option, connect repo. If none, ask if they want to create a new project, prompt for name, and connect repoId to project - // const projects = await getProjectsByOrgReq(settings.apiKey, settings.orgId); - - // const projectsNoRepoId = projects.filter((project) => !project.repoId); - - // let selectedProject = null; - - // if (projectsNoRepoId.length > 0) { - // const confirmExistingProject = await confirmExistingProjectLink(); - - // if (confirmExistingProject) { - // selectedProject = await promptProjectLinkSelection(projectsNoRepoId); - // const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.apiKey, selectedProject.id, repoId, repoFullName); - - // this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); - // } else { - // const projectName = await promptProjectName(projects); - // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); - - // this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); - // } - // } else { - // const projectName = await promptProjectName(projects); - // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); - - // this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); - // } - - // // add ci workflow to the repo if it doesn't already exist - // const githubWorkflowDir = getGithubWorkflowDir(); - // const ciHypFilePath = getCiHypFilePath(); - - // if (!(await fileExists(githubWorkflowDir))) { - // // create the directory - // await fs.mkdir(githubWorkflowDir, { recursive: true }); - // } - - // let shouldCreateCIFile = true; - // if (await fileExists(ciHypFilePath)) { - // // prompt if they want to replace it - // const confirmOverwrite = await confirmOverwriteCiHypFile(); - // if (!confirmOverwrite) { - // this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); - // shouldCreateCIFile = false; - // } - // } - - // if (shouldCreateCIFile) { - // await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); - // this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); - // } - - // this.log(chalk.green("Linking complete! 🎉")); - } + static override hidden = true; + + static override args = {}; + + // static override description = "Link a repo with a Modus App to a Hypermode Project"; + static override description = "Temporarily disabled during migration"; + + static override examples = ["<%= config.bin %> <%= command.id %>"]; + + static override flags = {}; + + public async getUserInstallationThroughAuthFlow(): Promise { + return new Promise((resolve, reject) => { + const server = http.createServer(async (req, res) => { + try { + const url = new URL(req.url ?? "", `http://${req.headers.host}`); + const installationId = url.searchParams.get("install_id"); + + if (!installationId) { + res.writeHead(400, { "Content-Type": "text/plain" }); + res.end("Installation ID not found in the request."); + return; + } + + res.writeHead(200, { "Content-Type": "text/html" }); + res.end(linkHTML); + + // Close all existing connections + server.closeAllConnections(); + + // Close the server and wait for it to actually close + server.close(async (err) => { + if (err) { + reject(err); + return; + } + + resolve(installationId); + }); + } catch (error) { + res.writeHead(500, { "Content-Type": "text/plain" }); + res.end("An error occurred during authentication."); + reject(error); + } + }); + + // Set a timeout for the server + const timeoutDuration = 300_000; // 300 seconds in milliseconds + const timeout = setTimeout(() => { + server.closeAllConnections(); + server.close(); + reject(new Error("Authentication timed out. Please try again.")); + }, timeoutDuration); + + // Listen on port 5051 for the redirect + server.listen(5051, "localhost", async () => { + try { + this.log("Opening link page..."); + await this.openLinkPage(); + } catch (error) { + server.close(); + reject(error); + } + }); + + // Ensure the timeout is cleared if the server closes successfully + server.on("close", () => { + clearTimeout(timeout); + }); + + // Handle server errors + server.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + } + + public async openLinkPage() { + // Open the Hypermode sign-in page in the default browser + const state = encodeURIComponent(JSON.stringify({ p: 5051, s: "cli" })); + const linkUrl = + "https://github.com/apps/hypermode/installations/new?state=" + state; + await open(linkUrl); + } + + public async run(): Promise { + this.error("Temporarily disabled during migration"); + return; + + // // check if the directory has a .git/config with a remote named 'origin', if not, throw an error and ask them to set that up + // const gitConfigFilePath = getGitConfigFilePath(); + + // if (!(await fileExists(gitConfigFilePath))) { + // throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); + // } + + // // Check if the current branch is 'main' + // let currentBranch = ""; + // try { + // currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); + // } catch (error) { + // this.log(chalk.red("Unable to determine the current branch.")); + // throw error; + // } + + // if (currentBranch !== "main") { + // this.log(chalk.red("You must be on the 'main' branch to link your repository.")); + // this.log("Please switch to the 'main' branch:"); + // this.log(` > ${chalk.blue("git checkout main")}`); + // this.log("or rename your current branch to 'main'."); + // this.log(` > ${chalk.blue("git branch -m main")}`); + // this.exit(1); + // } + + // const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); + + // if (!remoteUrl) { + // this.log(chalk.red("`hyp link` requires a git remote to work")); + // const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); + // const projectName = path.basename(gitRoot); + // this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); + // this.log(`And push your code:`); + // this.log(` > ${chalk.blue("git remote add origin )")}`); + // this.log(` > ${chalk.blue("git push -u origin main")}`); + + // this.exit(1); + // } + + // // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, + // // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json + + // const settingsFilePath = getSettingsFilePath(); + // if (!(await fileExists(settingsFilePath))) { + // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + // return; + // } + + // const settings = await readSettingsJson(settingsFilePath); + + // if (!settings.email || !settings.apiKey || !settings.orgId) { + // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + // return; + // } + + // const { gitOwner, repoName } = parseGitUrl(remoteUrl); + + // const repoFullName = `${gitOwner}/${repoName}`; + + // let installationId = null; + + // if (!settings.installationIds || !settings.installationIds[gitOwner]) { + // installationId = await this.getUserInstallationThroughAuthFlow(); + // await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); + // } else { + // installationId = settings.installationIds[gitOwner]; + // } + + // // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error + // const repoId = await sendGetRepoIdReq(settings.apiKey, installationId, remoteUrl); + + // if (!repoId) { + // throw new Error("No repoId found for the given installationId and gitUrl"); + // } + + // // get list of the projects for the user in this org, if any have no repoId, ask if they want to link it, or give option of none. + // // If they pick an option, connect repo. If none, ask if they want to create a new project, prompt for name, and connect repoId to project + // const projects = await getProjectsByOrgReq(settings.apiKey, settings.orgId); + + // const projectsNoRepoId = projects.filter((project) => !project.repoId); + + // let selectedProject = null; + + // if (projectsNoRepoId.length > 0) { + // const confirmExistingProject = await confirmExistingProjectLink(); + + // if (confirmExistingProject) { + // selectedProject = await promptProjectLinkSelection(projectsNoRepoId); + // const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.apiKey, selectedProject.id, repoId, repoFullName); + + // this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); + // } else { + // const projectName = await promptProjectName(projects); + // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); + + // this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); + // } + // } else { + // const projectName = await promptProjectName(projects); + // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); + + // this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); + // } + + // // add ci workflow to the repo if it doesn't already exist + // const githubWorkflowDir = getGithubWorkflowDir(); + // const ciHypFilePath = getCiHypFilePath(); + + // if (!(await fileExists(githubWorkflowDir))) { + // // create the directory + // await fs.mkdir(githubWorkflowDir, { recursive: true }); + // } + + // let shouldCreateCIFile = true; + // if (await fileExists(ciHypFilePath)) { + // // prompt if they want to replace it + // const confirmOverwrite = await confirmOverwriteCiHypFile(); + // if (!confirmOverwrite) { + // this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); + // shouldCreateCIFile = false; + // } + // } + + // if (shouldCreateCIFile) { + // await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); + // this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); + // } + + // this.log(chalk.green("Linking complete! 🎉")); + } } const linkHTML = ` diff --git a/src/commands/login/index.ts b/src/commands/login/index.ts index c03cd6b..e72f40d 100644 --- a/src/commands/login/index.ts +++ b/src/commands/login/index.ts @@ -3,14 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Command } from "@oclif/core"; -import chalk from "chalk"; import * as http from "node:http"; import { URL } from "node:url"; +import { Command } from "@oclif/core"; +import chalk from "chalk"; import open from "open"; import { sendGetOrgsReq } from "../../util/graphql.js"; -import { writeToSettingsFile, promptOrgSelection, readSettingsJson, getSettingsFilePath } from "../../util/index.js"; +import { + getSettingsFilePath, + promptOrgSelection, + readSettingsJson, + writeToSettingsFile, +} from "../../util/index.js"; const loginHTML = ` @@ -65,140 +70,154 @@ const loginHTML = ` `; export default class LoginIndex extends Command { - static override args = {}; - - static override description = "Log into Hypermode"; - - static override examples = ["<%= config.bin %> <%= command.id %>"]; - - static override flags = {}; - - public async openLoginPage() { - // Open the Hypermode sign-in page in the default browser - const loginUrl = "https://hypermode.com/callback?port=5051&type=cli"; - await open(loginUrl); - } - - public async run(): Promise { - const settings = await readSettingsJson(getSettingsFilePath()); - const apiKey = settings.apiKey; - - if (apiKey) { - const verifyResponse = await fetch("https://hypermode.com/api/api-key/verify", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - key: apiKey, - }), - }); - - const verifyResponseJson = await verifyResponse.json(); - - if (verifyResponseJson.valid) { - this.log("You are already logged in as " + chalk.dim(settings.email) + "! 🎉"); - return; - } - if (verifyResponseJson.error) { - this.log("Your API key is invalid or expired. Please log in again."); - } - } - - return new Promise((resolve, reject) => { - const server = http.createServer(async (req, res) => { - try { - const url = new URL(req.url ?? "", `http://${req.headers.host}`); - const jwt = url.searchParams.get("jwt"); - const email = url.searchParams.get("email"); - const userId = url.searchParams.get("user"); - - if (!jwt || !email || !userId) { - res.writeHead(400, { "Content-Type": "text/plain" }); - res.end("JWT, email, or userID not found in the request."); - return; - } - - const response = await fetch("https://hypermode.com/api/api-key/create", { - method: "POST", - headers: { - Authorization: `Bearer ${jwt}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - userId, - name: "CLI Access Key", - expiresIn: 60 * 60 * 24 * 365, // 365 days - prefix: "cli", - }), - }); - - const { data, error } = await response.json(); - const apiKey = data.key; - - if (!apiKey || error) { - throw new Error(error); - } - - res.writeHead(200, { "Content-Type": "text/html" }); - res.end(loginHTML); - - // Close all existing connections - server.closeAllConnections(); - - // Close the server and wait for it to actually close - server.close(async (err) => { - if (err) { - reject(err); - return; - } - - try { - const orgs = await sendGetOrgsReq(apiKey); - const selectedOrg = await promptOrgSelection(orgs); - await writeToSettingsFile(apiKey, email, selectedOrg.workspaces[0].id); - this.log("Successfully logged in as " + chalk.dim(email) + "! 🎉"); - resolve(); - } catch (error) { - reject(error); - } - }); - } catch (error) { - res.writeHead(500, { "Content-Type": "text/plain" }); - res.end("An error occurred during authentication."); - reject(error); - } - }); - - // Set a timeout for the server - const timeoutDuration = 300_000; // 300 seconds in milliseconds - const timeout = setTimeout(() => { - server.closeAllConnections(); - server.close(); - reject(new Error("Authentication timed out. Please try again.")); - }, timeoutDuration); - - // Listen on port 5051 for the redirect - server.listen(5051, "localhost", async () => { - try { - this.log("Opening login page..."); - await this.openLoginPage(); - } catch (error) { - server.close(); - reject(error); - } - }); - - // Ensure the timeout is cleared if the server closes successfully - server.on("close", () => { - clearTimeout(timeout); - }); - - // Handle server errors - server.on("error", (error) => { - clearTimeout(timeout); - reject(error); - }); - }); - } + static override args = {}; + + static override description = "Log into Hypermode"; + + static override examples = ["<%= config.bin %> <%= command.id %>"]; + + static override flags = {}; + + public async openLoginPage() { + // Open the Hypermode sign-in page in the default browser + const loginUrl = "https://hypermode.com/callback?port=5051&type=cli"; + await open(loginUrl); + } + + public async run(): Promise { + const settings = await readSettingsJson(getSettingsFilePath()); + const apiKey = settings.apiKey; + + if (apiKey) { + const verifyResponse = await fetch( + "https://hypermode.com/api/api-key/verify", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + key: apiKey, + }), + }, + ); + + const verifyResponseJson = await verifyResponse.json(); + + if (verifyResponseJson.valid) { + this.log( + "You are already logged in as " + chalk.dim(settings.email) + "! 🎉", + ); + return; + } + if (verifyResponseJson.error) { + this.log("Your API key is invalid or expired. Please log in again."); + } + } + + return new Promise((resolve, reject) => { + const server = http.createServer(async (req, res) => { + try { + const url = new URL(req.url ?? "", `http://${req.headers.host}`); + const jwt = url.searchParams.get("jwt"); + const email = url.searchParams.get("email"); + const userId = url.searchParams.get("user"); + + if (!jwt || !email || !userId) { + res.writeHead(400, { "Content-Type": "text/plain" }); + res.end("JWT, email, or userID not found in the request."); + return; + } + + const response = await fetch( + "https://hypermode.com/api/api-key/create", + { + method: "POST", + headers: { + Authorization: `Bearer ${jwt}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userId, + name: "CLI Access Key", + expiresIn: 60 * 60 * 24 * 365, // 365 days + prefix: "cli", + }), + }, + ); + + const { data, error } = await response.json(); + const apiKey = data.key; + + if (!apiKey || error) { + throw new Error(error); + } + + res.writeHead(200, { "Content-Type": "text/html" }); + res.end(loginHTML); + + // Close all existing connections + server.closeAllConnections(); + + // Close the server and wait for it to actually close + server.close(async (err) => { + if (err) { + reject(err); + return; + } + + try { + const orgs = await sendGetOrgsReq(apiKey); + const selectedOrg = await promptOrgSelection(orgs); + await writeToSettingsFile( + apiKey, + email, + selectedOrg.workspaces[0].id, + ); + this.log( + "Successfully logged in as " + chalk.dim(email) + "! 🎉", + ); + resolve(); + } catch (error) { + reject(error); + } + }); + } catch (error) { + res.writeHead(500, { "Content-Type": "text/plain" }); + res.end("An error occurred during authentication."); + reject(error); + } + }); + + // Set a timeout for the server + const timeoutDuration = 300_000; // 300 seconds in milliseconds + const timeout = setTimeout(() => { + server.closeAllConnections(); + server.close(); + reject(new Error("Authentication timed out. Please try again.")); + }, timeoutDuration); + + // Listen on port 5051 for the redirect + server.listen(5051, "localhost", async () => { + try { + this.log("Opening login page..."); + await this.openLoginPage(); + } catch (error) { + server.close(); + reject(error); + } + }); + + // Ensure the timeout is cleared if the server closes successfully + server.on("close", () => { + clearTimeout(timeout); + }); + + // Handle server errors + server.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + } } diff --git a/src/commands/logout/index.ts b/src/commands/logout/index.ts index e22ea94..ab9c3e2 100644 --- a/src/commands/logout/index.ts +++ b/src/commands/logout/index.ts @@ -7,43 +7,51 @@ import { Command } from "@oclif/core"; import chalk from "chalk"; import * as fs from "../../util/fs.js"; -import { fileExists, getSettingsFilePath, readSettingsJson } from "../../util/index.js"; +import { + fileExists, + getSettingsFilePath, + readSettingsJson, +} from "../../util/index.js"; export default class LogoutIndex extends Command { - static override args = {}; + static override args = {}; - static override description = "Log Hyp CLI out of Hypermode"; + static override description = "Log Hyp CLI out of Hypermode"; - static override examples = ["<%= config.bin %> <%= command.id %>"]; + static override examples = ["<%= config.bin %> <%= command.id %>"]; - static override flags = {}; + static override flags = {}; - public async run(): Promise { - const settingsFilePath = getSettingsFilePath(); + public async run(): Promise { + const settingsFilePath = getSettingsFilePath(); - // Check if .env.local file exists - if (!(await fileExists(settingsFilePath))) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } + // Check if .env.local file exists + if (!(await fileExists(settingsFilePath))) { + this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + return; + } - const res = await readSettingsJson(settingsFilePath); + const res = await readSettingsJson(settingsFilePath); - if (!res.email) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } + if (!res.email) { + this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + return; + } - console.log("Logging out of email: " + chalk.dim(res.email)); + console.log("Logging out of email: " + chalk.dim(res.email)); - const newSettingsContent = { - HYP_EMAIL: null, - HYP_API_KEY: null, - HYP_ORG_ID: null, - INSTALLATION_IDS: res.installationIds, - }; + const newSettingsContent = { + HYP_EMAIL: null, + HYP_API_KEY: null, + HYP_ORG_ID: null, + INSTALLATION_IDS: res.installationIds, + }; - // remove all content from settings.json - await fs.writeFile(settingsFilePath, JSON.stringify(newSettingsContent, null, 2), { flag: "w" }); - } + // remove all content from settings.json + await fs.writeFile( + settingsFilePath, + JSON.stringify(newSettingsContent, null, 2), + { flag: "w" }, + ); + } } diff --git a/src/commands/org/switch.ts b/src/commands/org/switch.ts index e26562b..ab4a135 100644 --- a/src/commands/org/switch.ts +++ b/src/commands/org/switch.ts @@ -7,35 +7,41 @@ import { Command } from "@oclif/core"; import chalk from "chalk"; import { sendGetOrgsReq } from "../../util/graphql.js"; -import { fileExists, getSettingsFilePath, promptOrgSelection, readSettingsJson, writeToSettingsFile } from "../../util/index.js"; +import { + fileExists, + getSettingsFilePath, + promptOrgSelection, + readSettingsJson, + writeToSettingsFile, +} from "../../util/index.js"; export default class OrgSwitch extends Command { - static override hidden = true; - static override args = {}; + static override hidden = true; + static override args = {}; - static override description = "Switch the current Hypermode organization"; + static override description = "Switch the current Hypermode organization"; - static override examples = ["<%= config.bin %> <%= command.id %>"]; + static override examples = ["<%= config.bin %> <%= command.id %>"]; - static override flags = {}; + static override flags = {}; - public async run(): Promise { - const settingsFilePath = getSettingsFilePath(); - if (!(await fileExists(settingsFilePath))) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } + public async run(): Promise { + const settingsFilePath = getSettingsFilePath(); + if (!(await fileExists(settingsFilePath))) { + this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + return; + } - const res = await readSettingsJson(settingsFilePath); + const res = await readSettingsJson(settingsFilePath); - if (!res.email || !res.apiKey || !res.workspaceId) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } + if (!res.email || !res.apiKey || !res.workspaceId) { + this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + return; + } - const orgs = await sendGetOrgsReq(res.apiKey); - const selectedOrg = await promptOrgSelection(orgs); + const orgs = await sendGetOrgsReq(res.apiKey); + const selectedOrg = await promptOrgSelection(orgs); - await writeToSettingsFile(res.apiKey, res.email, selectedOrg.id); - } + await writeToSettingsFile(res.apiKey, res.email, selectedOrg.id); + } } diff --git a/src/custom/header.ts b/src/custom/header.ts index 6c45adf..0bce063 100644 --- a/src/custom/header.ts +++ b/src/custom/header.ts @@ -6,10 +6,10 @@ import { getLogo } from "./logo.js"; export function getHeader(cliVersion: string): string { - let out = ""; - out += getLogo(); - out += "\n"; - out += `Hypermode CLI v${cliVersion}`; - out += "\n"; - return out; + let out = ""; + out += getLogo(); + out += "\n"; + out += `Hypermode CLI v${cliVersion}`; + out += "\n"; + return out; } diff --git a/src/custom/help.ts b/src/custom/help.ts index e78a33c..d28ed1b 100644 --- a/src/custom/help.ts +++ b/src/custom/help.ts @@ -3,213 +3,305 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Command, Help, Interfaces } from "@oclif/core"; +import { type Command, Help, type Interfaces } from "@oclif/core"; import chalk from "chalk"; import { getHeader } from "./header.js"; export default class CustomHelp extends Help { - private postPad = 0; - private prePad = 0; - private targetPad = 15; - formatCommand(command: Command.Loadable): string { - let out = ""; - out += chalk.bold("Usage:") + " " + chalk.bold.blueBright("hyp") + " " + command.id; - return out; - } - - formatCommands(commands: Command.Loadable[]): string { - let out = ""; - out += chalk.bold("Commands:") + "\n"; - - for (const command of commands) { - if (command.id === "autocomplete") continue; - - const rawName = command.id.includes(":") ? command.id.split(":")[1] : command.id; - const name = chalk.bold.blueBright(rawName); - const prePadding = " ".repeat(Math.max(1, this.prePad - rawName.length)); - const args = - Object.keys(command.args).length > 0 - ? Object.entries(command.args) - .map((v) => { - if (!v[1].hidden && v[1].required && v[1].description && v[1].description.indexOf("-|-") > 0) { - return v[1].description.split("-|-")[0]; - } - - return ""; - }) - .join(" ") - : ""; - const postPadding = " ".repeat(Math.max(1, this.postPad - args.length)); - const description = command.description!; - const aliases = command.aliases.length > 0 ? chalk.dim(" (" + command.aliases.join("/") + ")") : ""; - - out += " " + name + prePadding + chalk.dim(args) + postPadding + description + aliases + "\n"; - } - - return out.trim(); - } - - formatHeader(): string { - return getHeader(this.config.version); - } - - formatRoot(): string { - let out = ""; - out += chalk.bold.blueBright("Hypermode") + " - Build Intelligent APIs. \n\n"; - - // Usage: hyp [...flags] [...args] - out += chalk.bold("Usage: hyp") + " " + chalk.dim("") + " " + chalk.bold.blueBright("[...flags]") + " " + chalk.bold("[...args]"); - return out; - } - - formatRootFooter(): string { - let out = ""; - out += "View the docs:" + " ".repeat(Math.max(1, this.prePad + this.postPad - 12)) + chalk.blueBright("https://docs.hypermode.com") + "\n"; - // out += "View the repo:" + " ".repeat(Math.max(1, this.pre_pad + this.post_pad - 12)) + chalk.blueBright("https://github.com/HypermodeInc/modus") + "\n"; - - out += "\n"; - out += "Made with ♥︎ by Hypermode"; - return out; - } - - formatTopic(topic: Interfaces.Topic): string { - let out = ""; - out += chalk.bold.blueBright("Hypermode") + " Help \n\n"; - if (topic.description) out += chalk.dim(topic.description) + "\n"; - - out += chalk.bold("Usage: hyp " + topic.name) + " " + chalk.bold.blue("[command]") + "\n"; - return out; - } - - formatTopics(topics: Interfaces.Topic[]): string { - let out = ""; - if (topics.some((v) => !v.hidden)) out += chalk.bold("Tools:") + "\n"; - else return out; - - for (const topic of topics) { - if (topic.hidden) continue; - out += " " + chalk.bold.blue(topic.name) + " ".repeat(Math.max(1, this.prePad + this.postPad - topic.name.length)) + topic.description + "\n"; - } - - return out.trim(); - } - - async showCommandHelp(command: Command.Loadable): Promise { - this.log(this.formatHeader()); - const margin = 20; - const name = command.id.replaceAll(":", " "); - const args = Object.keys(command.args); - const flags = Object.keys(command.flags); - - this.log(chalk.bold.blueBright("Hypermode") + " Help " + chalk.dim("(v0.0.0)") + "\n"); - - if (command.description) this.log(chalk.dim(command.description)); - - this.log(chalk.bold("Usage:") + " " + chalk.bold("hyp " + name) + (args.length > 0 ? " [...args]" : "") + (flags.length > 0 ? chalk.blueBright(" [...flags]") : "") + "\n"); - // if (examples) { - // this.log(); - // this.log(chalk.bold("Examples:") + "\n"); - // for (const example of examples) this.log(" " + chalk.dim(example)); - // } - - if (flags.length > 0) { - this.log(chalk.bold("Flags:")); - for (const flag of Object.values(command.flags)) this.log(" " + chalk.bold.blueBright("--" + flag.name) + " ".repeat(margin - flag.name.length) + flag.description); - } - - if (args.length > 0) { - this.log(chalk.bold("Args:")); - for (const arg of Object.values(command.args)) { - let desc = arg.description; - if (arg.description?.includes("-|-")) { - desc = arg.description.split("-|-")[1]; - } - - this.log(" " + chalk.bold.blueBright(arg.name) + " ".repeat(Math.max(1, margin + 2 - arg.name.length)) + desc); - } - } - } - - async showRootHelp(): Promise { - this.log(this.formatHeader()); - let rootTopics = this.sortedTopics; - let rootCommands = this.sortedCommands; - const state = this.config.pjson?.oclif?.state; - if (state) { - this.log(state === "deprecated" ? `${this.config.bin} is deprecated` : `${this.config.bin} is in ${state}.\n`); - } - - this.log(this.formatRoot()); - this.log(""); - if (!this.opts.all) { - rootTopics = rootTopics.filter((t) => !t.name.includes(":")); - rootCommands = rootCommands.filter((c) => !c.id.includes(":")); - } - - for (const command of rootCommands) { - if (command.id.length > this.prePad) this.prePad = command.id.length; - const args = - Object.keys(command.args).length > 0 - ? Object.entries(command.args) - .map((v) => { - if (!v[1].hidden && v[1].required && v[1].description && v[1].description.indexOf("-|-") > 0) { - return v[1].description.split("-|-")[0]; - } - - return ""; - }) - .join(" ") - : ""; - if (args.length > this.postPad) this.postPad = args.length; - } - - this.postPad = 6 + this.prePad + this.postPad > this.targetPad ? 6 + this.prePad + this.postPad - this.targetPad : this.targetPad - this.prePad; - this.prePad += 2; - - if (rootTopics.length > 0) { - this.log(this.formatTopics(rootTopics)); - this.log(""); - } - - if (rootCommands.length > 0) { - rootCommands = rootCommands.filter((c) => c.id); - this.log(this.formatCommands(rootCommands)); - this.log(""); - } - - this.log(this.formatRootFooter()); - } - - async showTopicHelp(topic: Interfaces.Topic) { - this.log(this.formatHeader()); - const { name } = topic; - const commands = this.sortedCommands.filter((c) => c.id.startsWith(name + ":")); - for (const command of commands) { - if (command.id.split(":")[1].length > this.prePad) this.prePad = command.id.split(":")[1].length; - const args = - Object.keys(command.args).length > 0 - ? Object.entries(command.args) - .map((v) => { - if (!v[1].hidden && v[1].required && v[1].description && v[1].description.indexOf("-|-") > 0) { - return v[1].description.split("-|-")[0]; - } - - return ""; - }) - .join(" ") - : ""; - if (args.length > this.postPad) this.postPad = args.length; - } - - this.postPad = 6 + this.prePad + this.postPad > this.targetPad ? 6 + this.prePad + this.postPad - this.targetPad : this.targetPad - this.prePad; - this.prePad += 2; - const state = this.config.pjson?.oclif?.state; - if (state) this.log(`This topic is in ${state}.\n`); - this.log(this.formatTopic(topic)); - if (commands.length > 0) { - this.log(this.formatCommands(commands)); - this.log(""); - } - } + private postPad = 0; + private prePad = 0; + private targetPad = 15; + formatCommand(command: Command.Loadable): string { + let out = ""; + out += + chalk.bold("Usage:") + + " " + + chalk.bold.blueBright("hyp") + + " " + + command.id; + return out; + } + + formatCommands(commands: Command.Loadable[]): string { + let out = ""; + out += chalk.bold("Commands:") + "\n"; + + for (const command of commands) { + if (command.id === "autocomplete") continue; + + const rawName = command.id.includes(":") + ? command.id.split(":")[1] + : command.id; + const name = chalk.bold.blueBright(rawName); + const prePadding = " ".repeat(Math.max(1, this.prePad - rawName.length)); + const args = + Object.keys(command.args).length > 0 + ? Object.entries(command.args) + .map((v) => { + if ( + !v[1].hidden && + v[1].required && + v[1].description && + v[1].description.indexOf("-|-") > 0 + ) { + return v[1].description.split("-|-")[0]; + } + + return ""; + }) + .join(" ") + : ""; + const postPadding = " ".repeat(Math.max(1, this.postPad - args.length)); + const description = command.description!; + const aliases = + command.aliases.length > 0 + ? chalk.dim(" (" + command.aliases.join("/") + ")") + : ""; + + out += + " " + + name + + prePadding + + chalk.dim(args) + + postPadding + + description + + aliases + + "\n"; + } + + return out.trim(); + } + + formatHeader(): string { + return getHeader(this.config.version); + } + + formatRoot(): string { + let out = ""; + out += + chalk.bold.blueBright("Hypermode") + " - Build Intelligent APIs. \n\n"; + + // Usage: hyp [...flags] [...args] + out += + chalk.bold("Usage: hyp") + + " " + + chalk.dim("") + + " " + + chalk.bold.blueBright("[...flags]") + + " " + + chalk.bold("[...args]"); + return out; + } + + formatRootFooter(): string { + let out = ""; + out += + "View the docs:" + + " ".repeat(Math.max(1, this.prePad + this.postPad - 12)) + + chalk.blueBright("https://docs.hypermode.com") + + "\n"; + // out += "View the repo:" + " ".repeat(Math.max(1, this.pre_pad + this.post_pad - 12)) + chalk.blueBright("https://github.com/HypermodeInc/modus") + "\n"; + + out += "\n"; + out += "Made with ♥︎ by Hypermode"; + return out; + } + + formatTopic(topic: Interfaces.Topic): string { + let out = ""; + out += chalk.bold.blueBright("Hypermode") + " Help \n\n"; + if (topic.description) out += chalk.dim(topic.description) + "\n"; + + out += + chalk.bold("Usage: hyp " + topic.name) + + " " + + chalk.bold.blue("[command]") + + "\n"; + return out; + } + + formatTopics(topics: Interfaces.Topic[]): string { + let out = ""; + if (topics.some((v) => !v.hidden)) out += chalk.bold("Tools:") + "\n"; + else return out; + + for (const topic of topics) { + if (topic.hidden) continue; + out += + " " + + chalk.bold.blue(topic.name) + + " ".repeat( + Math.max(1, this.prePad + this.postPad - topic.name.length), + ) + + topic.description + + "\n"; + } + + return out.trim(); + } + + async showCommandHelp(command: Command.Loadable): Promise { + this.log(this.formatHeader()); + const margin = 20; + const name = command.id.replaceAll(":", " "); + const args = Object.keys(command.args); + const flags = Object.keys(command.flags); + + this.log( + chalk.bold.blueBright("Hypermode") + + " Help " + + chalk.dim("(v0.0.0)") + + "\n", + ); + + if (command.description) this.log(chalk.dim(command.description)); + + this.log( + chalk.bold("Usage:") + + " " + + chalk.bold("hyp " + name) + + (args.length > 0 ? " [...args]" : "") + + (flags.length > 0 ? chalk.blueBright(" [...flags]") : "") + + "\n", + ); + // if (examples) { + // this.log(); + // this.log(chalk.bold("Examples:") + "\n"); + // for (const example of examples) this.log(" " + chalk.dim(example)); + // } + + if (flags.length > 0) { + this.log(chalk.bold("Flags:")); + for (const flag of Object.values(command.flags)) + this.log( + " " + + chalk.bold.blueBright("--" + flag.name) + + " ".repeat(margin - flag.name.length) + + flag.description, + ); + } + + if (args.length > 0) { + this.log(chalk.bold("Args:")); + for (const arg of Object.values(command.args)) { + let desc = arg.description; + if (arg.description?.includes("-|-")) { + desc = arg.description.split("-|-")[1]; + } + + this.log( + " " + + chalk.bold.blueBright(arg.name) + + " ".repeat(Math.max(1, margin + 2 - arg.name.length)) + + desc, + ); + } + } + } + + async showRootHelp(): Promise { + this.log(this.formatHeader()); + let rootTopics = this.sortedTopics; + let rootCommands = this.sortedCommands; + const state = this.config.pjson?.oclif?.state; + if (state) { + this.log( + state === "deprecated" + ? `${this.config.bin} is deprecated` + : `${this.config.bin} is in ${state}.\n`, + ); + } + + this.log(this.formatRoot()); + this.log(""); + if (!this.opts.all) { + rootTopics = rootTopics.filter((t) => !t.name.includes(":")); + rootCommands = rootCommands.filter((c) => !c.id.includes(":")); + } + + for (const command of rootCommands) { + if (command.id.length > this.prePad) this.prePad = command.id.length; + const args = + Object.keys(command.args).length > 0 + ? Object.entries(command.args) + .map((v) => { + if ( + !v[1].hidden && + v[1].required && + v[1].description && + v[1].description.indexOf("-|-") > 0 + ) { + return v[1].description.split("-|-")[0]; + } + + return ""; + }) + .join(" ") + : ""; + if (args.length > this.postPad) this.postPad = args.length; + } + + this.postPad = + 6 + this.prePad + this.postPad > this.targetPad + ? 6 + this.prePad + this.postPad - this.targetPad + : this.targetPad - this.prePad; + this.prePad += 2; + + if (rootTopics.length > 0) { + this.log(this.formatTopics(rootTopics)); + this.log(""); + } + + if (rootCommands.length > 0) { + rootCommands = rootCommands.filter((c) => c.id); + this.log(this.formatCommands(rootCommands)); + this.log(""); + } + + this.log(this.formatRootFooter()); + } + + async showTopicHelp(topic: Interfaces.Topic) { + this.log(this.formatHeader()); + const { name } = topic; + const commands = this.sortedCommands.filter((c) => + c.id.startsWith(name + ":"), + ); + for (const command of commands) { + if (command.id.split(":")[1].length > this.prePad) + this.prePad = command.id.split(":")[1].length; + const args = + Object.keys(command.args).length > 0 + ? Object.entries(command.args) + .map((v) => { + if ( + !v[1].hidden && + v[1].required && + v[1].description && + v[1].description.indexOf("-|-") > 0 + ) { + return v[1].description.split("-|-")[0]; + } + + return ""; + }) + .join(" ") + : ""; + if (args.length > this.postPad) this.postPad = args.length; + } + + this.postPad = + 6 + this.prePad + this.postPad > this.targetPad + ? 6 + this.prePad + this.postPad - this.targetPad + : this.targetPad - this.prePad; + this.prePad += 2; + const state = this.config.pjson?.oclif?.state; + if (state) this.log(`This topic is in ${state}.\n`); + this.log(this.formatTopic(topic)); + if (commands.length > 0) { + this.log(this.formatCommands(commands)); + this.log(""); + } + } } diff --git a/src/custom/logo.ts b/src/custom/logo.ts index f4857dc..d1cc44b 100644 --- a/src/custom/logo.ts +++ b/src/custom/logo.ts @@ -14,5 +14,5 @@ const logo = String.raw` `; export function getLogo(): string { - return gradient(["#E3BFFF", "#602AF8"]).multiline(logo); + return gradient(["#E3BFFF", "#602AF8"]).multiline(logo); } diff --git a/src/util/fs.ts b/src/util/fs.ts index d685b05..97f2e54 100644 --- a/src/util/fs.ts +++ b/src/util/fs.ts @@ -7,10 +7,10 @@ import fs from "node:fs"; export * from "node:fs/promises"; export async function exists(path: string) { - try { - await fs.promises.stat(path); - return true; - } catch { - return false; - } + try { + await fs.promises.stat(path); + return true; + } catch { + return false; + } } diff --git a/src/util/graphql.ts b/src/util/graphql.ts index 72de44e..b1123cf 100644 --- a/src/util/graphql.ts +++ b/src/util/graphql.ts @@ -3,46 +3,53 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Org, App } from "../util/types.js"; -import { getSlugFromName } from "./index.js"; import chalk from "chalk"; +import type { App, Org } from "../util/types.js"; +import { getSlugFromName } from "./index.js"; -export async function sendGraphQLReqToHypermode(apiKey: string, query: string): Promise { - const url = "https://api.hypermode.com/graphql"; - - const options = { - body: JSON.stringify({ query }), - headers: { - "X-API-Key": apiKey, - "Content-Type": "application/json", - }, - method: "POST", - }; - - try { - const response = await fetch(url, options); - - if (!response.ok) { - if (response.status === 401) { - console.error(`Unauthorized. Please try ${chalk.blueBright("hyp login")} again.`); - throw new Error("Unauthorized: Invalid or expired API key."); - } else { - throw new Error(`HTTP Error: ${response.status} ${response.statusText}`); - } - } - - const data = await response.json(); - return data; - } catch (error: any) { - throw new Error(`Failed to send GraphQL request: ${error?.message}`); - } +export async function sendGraphQLReqToHypermode( + apiKey: string, + query: string, +): Promise { + const url = "https://api.hypermode.com/graphql"; + + const options = { + body: JSON.stringify({ query }), + headers: { + "X-API-Key": apiKey, + "Content-Type": "application/json", + }, + method: "POST", + }; + + try { + const response = await fetch(url, options); + + if (!response.ok) { + if (response.status === 401) { + console.error( + `Unauthorized. Please try ${chalk.blueBright("hyp login")} again.`, + ); + throw new Error("Unauthorized: Invalid or expired API key."); + } else { + throw new Error( + `HTTP Error: ${response.status} ${response.statusText}`, + ); + } + } + + const data = await response.json(); + return data; + } catch (error: any) { + throw new Error(`Failed to send GraphQL request: ${error?.message}`); + } } /** * Queries working with new Data Model */ export async function sendGetOrgsReq(apiKey: string): Promise { - const query = ` + const query = ` query GetOrgs { getOrgs { id @@ -55,19 +62,24 @@ export async function sendGetOrgsReq(apiKey: string): Promise { } }`; - const data: any = await sendGraphQLReqToHypermode(apiKey, query); + const data: any = await sendGraphQLReqToHypermode(apiKey, query); - const orgs: Org[] = data.data.getOrgs; + const orgs: Org[] = data.data.getOrgs; - return orgs; + return orgs; } /** * Queries not yet working with new Data Model */ -export async function sendMapRepoAndFinishProjectCreationReq(apiKey: string, id: string, repoId: string, repoName: string): Promise { - const query = ` +export async function sendMapRepoAndFinishProjectCreationReq( + apiKey: string, + id: string, + repoId: string, + repoName: string, +): Promise { + const query = ` mutation MapRepoAndFinishProjectCreation { mapRepoAndFinishProjectCreation(input: {id: "${id}", repoName: "${repoName}", repoId: "${repoId}", sourceType: CUSTOM, defaultBranchName: "main"}) { id @@ -76,16 +88,22 @@ export async function sendMapRepoAndFinishProjectCreationReq(apiKey: string, id: } }`; - const data: any = await sendGraphQLReqToHypermode(apiKey, query); + const data: any = await sendGraphQLReqToHypermode(apiKey, query); - const project: App = data.data.mapRepoAndFinishProjectCreation; + const project: App = data.data.mapRepoAndFinishProjectCreation; - return project; + return project; } -export async function sendCreateProjectReq(apiKey: string, orgId: string, projectName: string, repoId: string, repoName: string): Promise { - const slug = getSlugFromName(projectName); - const query = ` +export async function sendCreateProjectReq( + apiKey: string, + orgId: string, + projectName: string, + repoId: string, + repoName: string, +): Promise { + const slug = getSlugFromName(projectName); + const query = ` mutation CreateProjectBranchRuntime { createProjectBranchRuntime(input: {orgId: "${orgId}", clusterId: "clu-018f07d5-2446-7dbe-a766-dfab00c726de", name: "${projectName}", slug: "${slug}", repoId: "${repoId}", repoName: "${repoName}", sourceType: CUSTOM, defaultBranchName: "main"} ) { @@ -95,15 +113,18 @@ export async function sendCreateProjectReq(apiKey: string, orgId: string, projec } }`; - const res: any = await sendGraphQLReqToHypermode(apiKey, query); + const res: any = await sendGraphQLReqToHypermode(apiKey, query); - const project: App = res.data.createProjectBranchRuntime; + const project: App = res.data.createProjectBranchRuntime; - return project; + return project; } -export async function getProjectsByOrgReq(apiKey: string, orgId: string): Promise { - const query = ` +export async function getProjectsByOrgReq( + apiKey: string, + orgId: string, +): Promise { + const query = ` query GetProjectsByOrg { getOrg(id: "${orgId}") { id @@ -115,24 +136,28 @@ export async function getProjectsByOrgReq(apiKey: string, orgId: string): Promis } }`; - const data: any = await sendGraphQLReqToHypermode(apiKey, query); + const data: any = await sendGraphQLReqToHypermode(apiKey, query); - const projects: App[] = data.data.getOrg.projects; + const projects: App[] = data.data.getOrg.projects; - return projects; + return projects; } -export async function sendGetRepoIdReq(apiKey: string, installationId: string, gitUrl: string): Promise { - const query = ` +export async function sendGetRepoIdReq( + apiKey: string, + installationId: string, + gitUrl: string, +): Promise { + const query = ` query getUserRepoIdByUrl { getUserRepoIdByUrl(installationId: "${installationId}", gitUrl: "${gitUrl}") }`; - const res: any = await sendGraphQLReqToHypermode(apiKey, query); + const res: any = await sendGraphQLReqToHypermode(apiKey, query); - if (!res.data.getUserRepoIdByUrl) { - throw new Error("No repoId found for the given installationId and gitUrl"); - } + if (!res.data.getUserRepoIdByUrl) { + throw new Error("No repoId found for the given installationId and gitUrl"); + } - return res.data.getUserRepoIdByUrl; + return res.data.getUserRepoIdByUrl; } diff --git a/src/util/index.ts b/src/util/index.ts index c4ee0d0..3831997 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -3,195 +3,233 @@ * SPDX-License-Identifier: Apache-2.0 */ +import os from "node:os"; +import * as path from "node:path"; import { ExitPromptError } from "@inquirer/core"; import * as inquirer from "@inquirer/prompts"; +import slugify from "@sindresorhus/slugify"; import chalk from "chalk"; import * as fs from "../util/fs.js"; -import slugify from "@sindresorhus/slugify"; -import * as path from "node:path"; -import os from "node:os"; -import { Org, App } from "../util/types.js"; +import type { App, Org } from "../util/types.js"; export async function promptOrgSelection(orgs: Org[]): Promise { - const choices = orgs.map((org) => ({ - name: org.slug, - value: org, - })); - try { - const selectedOrg = await inquirer.select({ - choices, - message: "Please select an workspace:", - }); - - return selectedOrg; - } catch (error) { - const error_ = error instanceof ExitPromptError ? new TypeError(chalk.red("Workspace selection prompt exited.")) : error; - throw error_; - } -} - -export async function promptProjectLinkSelection(projects: App[]): Promise { - const choices = projects.map((project) => ({ - name: project.name, - value: project, - })); - try { - const selectedProject = await inquirer.select({ - choices, - message: "Please select a project to link:", - }); - - return selectedProject; - } catch (error) { - const error_ = error instanceof ExitPromptError ? new TypeError(chalk.red("Project selection prompt exited.")) : error; - throw error_; - } + const choices = orgs.map((org) => ({ + name: org.slug, + value: org, + })); + try { + const selectedOrg = await inquirer.select({ + choices, + message: "Please select an workspace:", + }); + + return selectedOrg; + } catch (error) { + const error_ = + error instanceof ExitPromptError + ? new TypeError(chalk.red("Workspace selection prompt exited.")) + : error; + throw error_; + } +} + +export async function promptProjectLinkSelection( + projects: App[], +): Promise { + const choices = projects.map((project) => ({ + name: project.name, + value: project, + })); + try { + const selectedProject = await inquirer.select({ + choices, + message: "Please select a project to link:", + }); + + return selectedProject; + } catch (error) { + const error_ = + error instanceof ExitPromptError + ? new TypeError(chalk.red("Project selection prompt exited.")) + : error; + throw error_; + } } export async function promptProjectName(projects: App[]): Promise { - const projectName = await inquirer.input({ - message: "Creating a new project. Please enter a project name:", - }); + const projectName = await inquirer.input({ + message: "Creating a new project. Please enter a project name:", + }); - if (!validateProjectName(projectName)) { - console.log(chalk.red("Project name must be longer than 3 characters.")); - return promptProjectName(projects); - } + if (!validateProjectName(projectName)) { + console.log(chalk.red("Project name must be longer than 3 characters.")); + return promptProjectName(projects); + } - // check if project name already exists in projects - const projectNames = projects.map((project) => project.name); - if (projectNames.includes(projectName)) { - // re-prompt for project name - console.log(chalk.red("Project name already exists.")); - return promptProjectName(projects); - } + // check if project name already exists in projects + const projectNames = projects.map((project) => project.name); + if (projectNames.includes(projectName)) { + // re-prompt for project name + console.log(chalk.red("Project name already exists.")); + return promptProjectName(projects); + } - return projectName; + return projectName; } function validateProjectName(projectName: string): boolean { - return projectName.length > 3; + return projectName.length > 3; } export function getSlugFromName(name: string): string { - return slugify(name); + return slugify(name); } export async function confirmOverwriteCiHypFile(): Promise { - return inquirer.confirm({ - default: true, - message: "A ci-modus-build.yml file already exists. Would you like to overwrite it?", - }); + return inquirer.confirm({ + default: true, + message: + "A ci-modus-build.yml file already exists. Would you like to overwrite it?", + }); } export async function confirmExistingProjectLink(): Promise { - return inquirer.confirm({ - default: true, - message: "You have existing projects with no linked repositories. Would you like to select from these projects?", - }); + return inquirer.confirm({ + default: true, + message: + "You have existing projects with no linked repositories. Would you like to select from these projects?", + }); } export function getSettingsDir(): string { - return path.join(os.homedir(), ".hypermode"); + return path.join(os.homedir(), ".hypermode"); } export function getSettingsFilePath(): string { - const settingsDir = getSettingsDir(); - return path.join(settingsDir, "settings.json"); + const settingsDir = getSettingsDir(); + return path.join(settingsDir, "settings.json"); } export async function fileExists(filePath: string): Promise { - return fs.exists(filePath); + return fs.exists(filePath); } export function getGitDir(): string { - return path.join(process.cwd(), ".git"); + return path.join(process.cwd(), ".git"); } export function getGithubWorkflowDir(): string { - return path.join(process.cwd(), ".github", "workflows"); + return path.join(process.cwd(), ".github", "workflows"); } export function getCiHypFilePath(): string { - return path.join(getGithubWorkflowDir(), "ci-modus-build.yml"); + return path.join(getGithubWorkflowDir(), "ci-modus-build.yml"); } export function getGitConfigFilePath(): string { - return path.join(getGitDir(), "config"); -} - -export async function getGitRemoteUrl(filePath: string): Promise { - const content = await fs.readFile(filePath, "utf8"); - const remoteMatch = content.match(/\[remote "origin"]\n\s+url = (.*)/); - - if (!remoteMatch) { - return null; - } - - return remoteMatch[1]; -} - -export async function readSettingsJson(filePath: string): Promise<{ content: string; email: null | string; installationIds: { [key: string]: string } | null; apiKey: null | string; workspaceId: null | string }> { - const content = await fs.readFile(filePath, "utf8"); - - let email: null | string = null; - let apiKey: null | string = null; - let workspaceId: null | string = null; - let installationIds: { [key: string]: string } | null = null; - - try { - const jsonContent = JSON.parse(content); - email = jsonContent.HYP_EMAIL || null; - apiKey = jsonContent.HYP_API_KEY || null; - workspaceId = jsonContent.HYP_WORKSPACE_ID || null; - installationIds = jsonContent.INSTALLATION_IDS || null; - } catch { - // ignore error - } - - return { - content, - email, - installationIds, - apiKey, - workspaceId, - }; -} - -export async function writeToSettingsFile(apiKey: string, email: string, workspaceId: string): Promise { - const settingsDir = getSettingsDir(); - const settingsFilePath = getSettingsFilePath(); - - // Create the directory if it doesn't exist - if (!(await fileExists(settingsDir))) { - await fs.mkdir(settingsDir, { recursive: true }); - } - - const newSettingsContent: { HYP_EMAIL: string; HYP_API_KEY: string; HYP_WORKSPACE_ID: string; INSTALLATION_IDS: { [key: string]: string } | null } = { - HYP_EMAIL: email, - HYP_API_KEY: apiKey, - HYP_WORKSPACE_ID: workspaceId, - INSTALLATION_IDS: null, - }; - - if (await fileExists(settingsFilePath)) { - const settings = await readSettingsJson(settingsFilePath); - newSettingsContent.INSTALLATION_IDS = settings.installationIds; - } - - // Write the new content to the file, replacing any existing content - await fs.writeFile(settingsFilePath, JSON.stringify(newSettingsContent, null, 2), { flag: "w" }); -} - -export async function writeGithubInstallationIdToSettingsFile(gitOwner: string, installationId: string): Promise { - const settingsFilePath = getSettingsFilePath(); - const settings = await readSettingsJson(settingsFilePath); - - settings.installationIds = settings.installationIds || {}; - settings.installationIds[gitOwner] = installationId; - - const newSettingsContent = { ...settings }; - - await fs.writeFile(settingsFilePath, JSON.stringify(newSettingsContent, null, 2), { flag: "w" }); + return path.join(getGitDir(), "config"); +} + +export async function getGitRemoteUrl( + filePath: string, +): Promise { + const content = await fs.readFile(filePath, "utf8"); + const remoteMatch = content.match(/\[remote "origin"]\n\s+url = (.*)/); + + if (!remoteMatch) { + return null; + } + + return remoteMatch[1]; +} + +export async function readSettingsJson(filePath: string): Promise<{ + content: string; + email: null | string; + installationIds: { [key: string]: string } | null; + apiKey: null | string; + workspaceId: null | string; +}> { + const content = await fs.readFile(filePath, "utf8"); + + let email: null | string = null; + let apiKey: null | string = null; + let workspaceId: null | string = null; + let installationIds: { [key: string]: string } | null = null; + + try { + const jsonContent = JSON.parse(content); + email = jsonContent.HYP_EMAIL || null; + apiKey = jsonContent.HYP_API_KEY || null; + workspaceId = jsonContent.HYP_WORKSPACE_ID || null; + installationIds = jsonContent.INSTALLATION_IDS || null; + } catch { + // ignore error + } + + return { + content, + email, + installationIds, + apiKey, + workspaceId, + }; +} + +export async function writeToSettingsFile( + apiKey: string, + email: string, + workspaceId: string, +): Promise { + const settingsDir = getSettingsDir(); + const settingsFilePath = getSettingsFilePath(); + + // Create the directory if it doesn't exist + if (!(await fileExists(settingsDir))) { + await fs.mkdir(settingsDir, { recursive: true }); + } + + const newSettingsContent: { + HYP_EMAIL: string; + HYP_API_KEY: string; + HYP_WORKSPACE_ID: string; + INSTALLATION_IDS: { [key: string]: string } | null; + } = { + HYP_EMAIL: email, + HYP_API_KEY: apiKey, + HYP_WORKSPACE_ID: workspaceId, + INSTALLATION_IDS: null, + }; + + if (await fileExists(settingsFilePath)) { + const settings = await readSettingsJson(settingsFilePath); + newSettingsContent.INSTALLATION_IDS = settings.installationIds; + } + + // Write the new content to the file, replacing any existing content + await fs.writeFile( + settingsFilePath, + JSON.stringify(newSettingsContent, null, 2), + { flag: "w" }, + ); +} + +export async function writeGithubInstallationIdToSettingsFile( + gitOwner: string, + installationId: string, +): Promise { + const settingsFilePath = getSettingsFilePath(); + const settings = await readSettingsJson(settingsFilePath); + + settings.installationIds = settings.installationIds || {}; + settings.installationIds[gitOwner] = installationId; + + const newSettingsContent = { ...settings }; + + await fs.writeFile( + settingsFilePath, + JSON.stringify(newSettingsContent, null, 2), + { flag: "w" }, + ); } diff --git a/src/util/types.ts b/src/util/types.ts index 742abb9..2887e84 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -4,21 +4,21 @@ */ export type Org = { - id: string; - name: string; - slug: string; - workspaces: Workspace[]; + id: string; + name: string; + slug: string; + workspaces: Workspace[]; }; export type Workspace = { - id: string; - name: string; - slug: string; - apps: App[]; + id: string; + name: string; + slug: string; + apps: App[]; }; export type App = { - id: string; - name: string; - repoId: null | string; + id: string; + name: string; + repoId: null | string; }; diff --git a/tsconfig.json b/tsconfig.json index 641c6b0..b99d723 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,16 @@ { - "compilerOptions": { - "declaration": true, - "module": "NodeNext", - "outDir": "dist", - "rootDir": "src", - "strict": true, - "target": "ESNext", - "moduleResolution": "NodeNext", - "sourceMap": true - }, - "include": ["./src/**/*"], - "ts-node": { - "esm": true - } + "compilerOptions": { + "declaration": true, + "module": "NodeNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "target": "ESNext", + "moduleResolution": "NodeNext", + "sourceMap": true + }, + "include": ["./src/**/*"], + "ts-node": { + "esm": true + } }