From 05518e42920fc45dab8ee16519e8aa6d2fe0b860 Mon Sep 17 00:00:00 2001 From: Jon M Date: Wed, 26 Jun 2024 14:48:10 +0100 Subject: [PATCH] Initial commit --- .github/workflows/build.yml | 30 + .github/workflows/publish.yml | 29 + .gitignore | 137 ++ .npmignore | 8 + .prettierrc | 20 + LICENSE | 21 + README.md | 1 + package-lock.json | 2013 ++++++++++++++++++ package.json | 34 + src/create-tests.ts | 54 + src/helpers/checkIfInstalled.ts | 83 + src/helpers/copy.ts | 19 + src/helpers/exit.ts | 11 + src/helpers/getPackageManager.ts | 19 + src/helpers/handleFilesByLanguage.ts | 42 + src/helpers/howToRunTests.ts | 74 + src/helpers/index.ts | 11 + src/helpers/install.ts | 48 + src/helpers/isFolderEmpty.ts | 17 + src/helpers/isWriteable.ts | 20 + src/helpers/languageHandlers/handleDotnet.ts | 22 + src/helpers/languageHandlers/handleGo.ts | 20 + src/helpers/languageHandlers/handleJava.ts | 20 + src/helpers/languageHandlers/handleNodeJs.ts | 41 + src/helpers/languageHandlers/handlePhp.ts | 38 + src/helpers/languageHandlers/handlePython.ts | 44 + src/helpers/languageHandlers/handleRuby.ts | 51 + src/helpers/languageHandlers/index.ts | 7 + src/helpers/modifyComposerJson.ts | 18 + src/helpers/modifyPackageJson.ts | 18 + src/index.ts | 63 + src/inputs/apiKeyInput.ts | 51 + src/inputs/frameworkInput.ts | 35 + src/inputs/getProjectPath.ts | 43 + src/inputs/index.ts | 7 + src/inputs/installDependenciesInput.ts | 45 + src/inputs/languageInput.ts | 35 + src/inputs/projectNameInput.ts | 41 + src/inputs/serverIdInput.ts | 29 + src/options/frameworks.ts | 61 + src/options/index.ts | 2 + src/options/languages.ts | 63 + src/scaffolding.ts | 50 + src/types/createOptions.ts | 14 + src/types/frameworks.ts | 15 + src/types/index.ts | 5 + src/types/languages.ts | 19 + src/types/libraries.ts | 8 + src/types/packageManager.ts | 8 + tsconfig.json | 21 + tsup.config.ts | 26 + 51 files changed, 3611 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 .prettierrc create mode 100644 LICENSE create mode 100644 README.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/create-tests.ts create mode 100644 src/helpers/checkIfInstalled.ts create mode 100644 src/helpers/copy.ts create mode 100644 src/helpers/exit.ts create mode 100644 src/helpers/getPackageManager.ts create mode 100644 src/helpers/handleFilesByLanguage.ts create mode 100644 src/helpers/howToRunTests.ts create mode 100644 src/helpers/index.ts create mode 100644 src/helpers/install.ts create mode 100644 src/helpers/isFolderEmpty.ts create mode 100644 src/helpers/isWriteable.ts create mode 100644 src/helpers/languageHandlers/handleDotnet.ts create mode 100644 src/helpers/languageHandlers/handleGo.ts create mode 100644 src/helpers/languageHandlers/handleJava.ts create mode 100644 src/helpers/languageHandlers/handleNodeJs.ts create mode 100644 src/helpers/languageHandlers/handlePhp.ts create mode 100644 src/helpers/languageHandlers/handlePython.ts create mode 100644 src/helpers/languageHandlers/handleRuby.ts create mode 100644 src/helpers/languageHandlers/index.ts create mode 100644 src/helpers/modifyComposerJson.ts create mode 100644 src/helpers/modifyPackageJson.ts create mode 100755 src/index.ts create mode 100644 src/inputs/apiKeyInput.ts create mode 100644 src/inputs/frameworkInput.ts create mode 100644 src/inputs/getProjectPath.ts create mode 100644 src/inputs/index.ts create mode 100644 src/inputs/installDependenciesInput.ts create mode 100644 src/inputs/languageInput.ts create mode 100644 src/inputs/projectNameInput.ts create mode 100644 src/inputs/serverIdInput.ts create mode 100644 src/options/frameworks.ts create mode 100644 src/options/index.ts create mode 100644 src/options/languages.ts create mode 100644 src/scaffolding.ts create mode 100644 src/types/createOptions.ts create mode 100644 src/types/frameworks.ts create mode 100644 src/types/index.ts create mode 100644 src/types/languages.ts create mode 100644 src/types/libraries.ts create mode 100644 src/types/packageManager.ts create mode 100644 tsconfig.json create mode 100644 tsup.config.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..8857e07 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ${{ vars.LINUX }} + timeout-minutes: 10 + steps: + - name: Checkout source code + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: ${{ vars.NODE_VERSION }} + - name: Set build number + uses: ./.github/actions/build-number + - name: Build + run: npm i && npm run build + - name: Notify on failure + if: ${{ failure() }} + uses: ./.github/actions/fail-notification + with: + webhook-url: ${{ secrets.TEAMS_BUILDS_WEBHOOK }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..90e1031 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,29 @@ +name: Publish + +on: + release: + types: [created] + +jobs: + publish: + runs-on: ${{ vars.LINUX }} + timeout-minutes: 10 + steps: + - name: Checkout source code + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: ${{ vars.NODE_VERSION }} + registry-url: https://registry.npmjs.org/ + - name: version + run: | + npm --no-git-tag-version --allow-same-version version `git describe --abbrev=0 --tags` + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Notify on failure + if: ${{ failure() }} + uses: ./.github/actions/fail-notification + with: + webhook-url: ${{ secrets.TEAMS_BUILDS_WEBHOOK }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65d7733 --- /dev/null +++ b/.gitignore @@ -0,0 +1,137 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +**/__pycache__/** + +.DS_Store +Thumbs.db + +examples/ diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..b7aecb8 --- /dev/null +++ b/.npmignore @@ -0,0 +1,8 @@ +/src +/node_modules + +.env +.DS_Store + +tsconfig.json +tsup.config.ts \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e5d1b78 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,20 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "es5", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "avoid", + "requirePragma": false, + "insertPragma": false, + "proseWrap": "preserve", + "htmlWhitespaceSensitivity": "css", + "endOfLine": "lf", + "embeddedLanguageFormatting": "auto", + "singleAttributePerLine": false +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f794123 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Mailosaur Ltd (https://mailosaur.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f57dc6c --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# create-mailosaur-draft \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d25d79b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2013 @@ +{ + "name": "create-mailosaur", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "create-mailosaur", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.2", + "fs-extra": "^11.2.0", + "picocolors": "^1.0.1", + "prompts": "^2.4.2", + "tsup": "^8.1.0", + "typescript": "^5.4.5", + "validate-npm-package-name": "^5.0.1" + }, + "bin": { + "create-mailosaur": "dist/index.mjs" + }, + "devDependencies": { + "@types/cross-spawn": "^6.0.6", + "@types/fs-extra": "^11.0.4", + "@types/node": "^20.14.2", + "@types/prompts": "^2.4.9", + "@types/validate-npm-package-name": "^4.0.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.4.tgz", + "integrity": "sha512-Zrm+B33R4LWPLjDEVnEqt2+SLTATlru1q/xYKVn8oVTbiRBGmK2VIMoIYGJDGyftnGaC788IuzGFAlb7IQ0Y8A==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.4.tgz", + "integrity": "sha512-E7H/yTd8kGQfY4z9t3nRPk/hrhaCajfA3YSQSBrst8B+3uTcgsi8N+ZWYCaeIDsiVs6m65JPCaQN/DxBRclF3A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.4.tgz", + "integrity": "sha512-fYFnz+ObClJ3dNiITySBUx+oNalYUT18/AryMxfovLkYWbutXsct3Wz2ZWAcGGppp+RVVX5FiXeLYGi97umisA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.4.tgz", + "integrity": "sha512-mDqmlge3hFbEPbCWxp4fM6hqq7aZfLEHZAKGP9viq9wMUBVQx202aDIfc3l+d2cKhUJM741VrCXEzRFhPDKH3Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.4.tgz", + "integrity": "sha512-72eaIrDZDSiWqpmCzVaBD58c8ea8cw/U0fq/PPOTqE3c53D0xVMRt2ooIABZ6/wj99Y+h4ksT/+I+srCDLU9TA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.4.tgz", + "integrity": "sha512-uBsuwRMehGmw1JC7Vecu/upOjTsMhgahmDkWhGLWxIgUn2x/Y4tIwUZngsmVb6XyPSTXJYS4YiASKPcm9Zitag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.4.tgz", + "integrity": "sha512-8JfuSC6YMSAEIZIWNL3GtdUT5NhUA/CMUCpZdDRolUXNAXEE/Vbpe6qlGLpfThtY5NwXq8Hi4nJy4YfPh+TwAg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.4.tgz", + "integrity": "sha512-8d9y9eQhxv4ef7JmXny7591P/PYsDFc4+STaxC1GBv0tMyCdyWfXu2jBuqRsyhY8uL2HU8uPyscgE2KxCY9imQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.4.tgz", + "integrity": "sha512-2rqFFefpYmpMs+FWjkzSgXg5vViocqpq5a1PSRgT0AvSgxoXmGF17qfGAzKedg6wAwyM7UltrKVo9kxaJLMF/g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.4.tgz", + "integrity": "sha512-/GLD2orjNU50v9PcxNpYZi+y8dJ7e7/LhQukN3S4jNDXCKkyyiyAz9zDw3siZ7Eh1tRcnCHAo/WcqKMzmi4eMQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.4.tgz", + "integrity": "sha512-pNftBl7m/tFG3t2m/tSjuYeWIffzwAZT9m08+9DPLizxVOsUl8DdFzn9HvJrTQwe3wvJnwTdl92AonY36w/25g==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.4.tgz", + "integrity": "sha512-cSD2gzCK5LuVX+hszzXQzlWya6c7hilO71L9h4KHwqI4qeqZ57bAtkgcC2YioXjsbfAv4lPn3qe3b00Zt+jIfQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.4.tgz", + "integrity": "sha512-qtzAd3BJh7UdbiXCrg6npWLYU0YpufsV9XlufKhMhYMJGJCdfX/G6+PNd0+v877X1JG5VmjBLUiFB0o8EUSicA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.4.tgz", + "integrity": "sha512-yB8AYzOTaL0D5+2a4xEy7OVvbcypvDR05MsB/VVPVA7nL4hc5w5Dyd/ddnayStDgJE59fAgNEOdLhBxjfx5+dg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.4.tgz", + "integrity": "sha512-Y5AgOuVzPjQdgU59ramLoqSSiXddu7F3F+LI5hYy/d1UHN7K5oLzYBDZe23QmQJ9PIVUXwOdKJ/jZahPdxzm9w==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.4.tgz", + "integrity": "sha512-Iqc/l/FFwtt8FoTK9riYv9zQNms7B8u+vAI/rxKuN10HgQIXaPzKZc479lZ0x6+vKVQbu55GdpYpeNWzjOhgbA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.4.tgz", + "integrity": "sha512-Td9jv782UMAFsuLZINfUpoF5mZIbAj+jv1YVtE58rFtfvoKRiKSkRGQfHTgKamLVT/fO7203bHa3wU122V/Bdg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.4.tgz", + "integrity": "sha512-Awn38oSXxsPMQxaV0Ipb7W/gxZtk5Tx3+W+rAPdZkyEhQ6968r9NvtkjhnhbEgWXYbgV+JEONJ6PcdBS+nlcpA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.4.tgz", + "integrity": "sha512-IsUmQeCY0aU374R82fxIPu6vkOybWIMc3hVGZ3ChRwL9hA1TwY+tS0lgFWV5+F1+1ssuvvXt3HFqe8roCip8Hg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.4.tgz", + "integrity": "sha512-hsKhgZ4teLUaDA6FG/QIu2q0rI6I36tZVfM4DBZv3BG0mkMIdEnMbhc4xwLvLJSS22uWmaVkFkqWgIS0gPIm+A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.4.tgz", + "integrity": "sha512-UUfMgMoXPoA/bvGUNfUBFLCh0gt9dxZYIx9W4rfJr7+hKe5jxxHmfOK8YSH4qsHLLN4Ck8JZ+v7Q5fIm1huErg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.4.tgz", + "integrity": "sha512-yIxbspZb5kGCAHWm8dexALQ9en1IYDfErzjSEq1KzXFniHv019VT3mNtTK7t8qdy4TwT6QYHI9sEZabONHg+aw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.4.tgz", + "integrity": "sha512-sywLRD3UK/qRJt0oBwdpYLBibk7KiRfbswmWRDabuncQYSlf8aLEEUor/oP6KRz8KEG+HoiVLBhPRD5JWjS8Sg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prompts": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz", + "integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "kleur": "^3.0.3" + } + }, + "node_modules/@types/validate-npm-package-name": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz", + "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==", + "dev": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bundle-require": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.2.1.tgz", + "integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.17" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/esbuild": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.4.tgz", + "integrity": "sha512-sFMcNNrj+Q0ZDolrp5pDhH0nRPN9hLIM3fRPwgbLYJeSHHgnXSnbV3xYgSVuOeLWH9c73VwmEverVzupIv5xuA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.4", + "@esbuild/android-arm": "0.21.4", + "@esbuild/android-arm64": "0.21.4", + "@esbuild/android-x64": "0.21.4", + "@esbuild/darwin-arm64": "0.21.4", + "@esbuild/darwin-x64": "0.21.4", + "@esbuild/freebsd-arm64": "0.21.4", + "@esbuild/freebsd-x64": "0.21.4", + "@esbuild/linux-arm": "0.21.4", + "@esbuild/linux-arm64": "0.21.4", + "@esbuild/linux-ia32": "0.21.4", + "@esbuild/linux-loong64": "0.21.4", + "@esbuild/linux-mips64el": "0.21.4", + "@esbuild/linux-ppc64": "0.21.4", + "@esbuild/linux-riscv64": "0.21.4", + "@esbuild/linux-s390x": "0.21.4", + "@esbuild/linux-x64": "0.21.4", + "@esbuild/netbsd-x64": "0.21.4", + "@esbuild/openbsd-x64": "0.21.4", + "@esbuild/sunos-x64": "0.21.4", + "@esbuild/win32-arm64": "0.21.4", + "@esbuild/win32-ia32": "0.21.4", + "@esbuild/win32-x64": "0.21.4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.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==", + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tsup": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.1.0.tgz", + "integrity": "sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg==", + "dependencies": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.21.4", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^4.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.0.2", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yaml": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.3.tgz", + "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6ca6290 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "create-mailosaur", + "version": "0.0.1", + "description": "", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "bin": { + "create-mailosaur": "./dist/index.mjs" + }, + "scripts": { + "build": "npm run fetch-examples && tsup", + "fetch-examples": "rm -rf ./src/examples && git clone https://github.com/mailosaur/examples.git ./src/examples" + }, + "author": "", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.2", + "fs-extra": "^11.2.0", + "picocolors": "^1.0.1", + "prompts": "^2.4.2", + "tsup": "^8.1.0", + "typescript": "^5.4.5", + "validate-npm-package-name": "^5.0.1" + }, + "devDependencies": { + "@types/cross-spawn": "^6.0.6", + "@types/fs-extra": "^11.0.4", + "@types/node": "^20.14.2", + "@types/prompts": "^2.4.9", + "@types/validate-npm-package-name": "^4.0.2" + } +} diff --git a/src/create-tests.ts b/src/create-tests.ts new file mode 100644 index 0000000..c59b7aa --- /dev/null +++ b/src/create-tests.ts @@ -0,0 +1,54 @@ +import fs from 'fs'; +import path, { dirname } from 'path'; + +import pc from 'picocolors'; + +import { CreateOptions } from '@/types'; +import { howToRunTests } from '@/helpers'; + +import { scaffoldSample } from './scaffolding'; + +export async function createTests(createOptions: CreateOptions) { + const { + packageManager, + projectPath, + projectName, + framework, + language, + installDependencies, + } = createOptions; + + const root = path.resolve(projectPath); + + fs.mkdirSync(root, { recursive: true }); + + const originalDirectory = process.cwd(); + + console.log( + `\nCreating ${pc.magenta(pc.bold(projectName))} at ${pc.magenta( + pc.bold(dirname(root)) + )}` + ); + + process.chdir(root); + + await scaffoldSample({ createOptions, root }); + + let cdpath: string; + + if (path.join(originalDirectory, projectName) === projectPath) { + cdpath = projectName; + } else { + cdpath = projectPath; + } + + console.log(`${pc.green(pc.bold('\nSuccess!'))}`); + + howToRunTests({ + cdpath, + framework, + language, + packageManager, + installDependencies, + }); +} diff --git a/src/helpers/checkIfInstalled.ts b/src/helpers/checkIfInstalled.ts new file mode 100644 index 0000000..dd778d0 --- /dev/null +++ b/src/helpers/checkIfInstalled.ts @@ -0,0 +1,83 @@ +import os from 'os'; + +import pc from 'picocolors'; +import spawn from 'cross-spawn'; + +import { Libraries } from '@/types'; + +import { exit } from './exit'; + +export function checkIfInstalled(library: Libraries) { + const args: string[] = []; + const checkCommand = os.platform() === 'win32' ? 'where' : 'command'; + + if (os.platform() !== 'win32') { + args.push('-v'); + } + + const child = spawn(checkCommand, [...args, library], { + stdio: 'ignore', + }); + + child.on('close', (code) => { + if (code !== 0) { + console.log( + pc.red( + `${library} is not installed. Please install ${library} to proceed.` + ) + ); + + handleSpecificLibraryError({ library }); + } + }); + + child.on('error', () => { + console.log( + pc.red( + `${library} is not installed. Please install ${library} to proceed.` + ) + ); + + handleSpecificLibraryError({ library }); + }); +} + +interface HandleSpecificLibraryErrorProps { + library: Libraries; +} + +function handleSpecificLibraryError({ + library, +}: HandleSpecificLibraryErrorProps) { + switch (library) { + case 'pip': + console.log( + 'Installation instructions: https://pip.pypa.io/en/stable/installation/' + ); + break; + case 'php': + console.log( + 'Installation instructions: https://www.php.net/manual/en/install.php' + ); + break; + case 'composer': + console.log( + 'Installation instructions: https://getcomposer.org/download/' + ); + break; + case 'python': + console.log( + 'Installation instructions: https://www.python.org/downloads/' + ); + break; + case 'ruby': + console.log( + 'Installation instructions: https://www.ruby-lang.org/en/documentation/installation/' + ); + break; + default: + break; + } + + return exit(1); +} diff --git a/src/helpers/copy.ts b/src/helpers/copy.ts new file mode 100644 index 0000000..a50179a --- /dev/null +++ b/src/helpers/copy.ts @@ -0,0 +1,19 @@ +import path from 'path'; +import glob from 'fast-glob'; +import fsExtra from 'fs-extra'; + +export async function copy(sourceDir: string, targetDir: string) { + try { + const files = await glob(['**/*'], { cwd: sourceDir, dot: true }); + + await Promise.all( + files.map(async (file) => { + const sourcePath = path.join(sourceDir, file); + const targetPath = path.join(targetDir, file); + await fsExtra.copy(sourcePath, targetPath); + }) + ); + } catch (err) { + console.error('Error copying files'); + } +} diff --git a/src/helpers/exit.ts b/src/helpers/exit.ts new file mode 100644 index 0000000..189308c --- /dev/null +++ b/src/helpers/exit.ts @@ -0,0 +1,11 @@ +import pc from 'picocolors'; + +export const exit = (code: 1 | 0) => { + if (code === 1) { + console.log(); + process.exit(code); + } + + console.error(`${pc.red(pc.bold('\nExiting'))}`); + process.exit(code); +}; diff --git a/src/helpers/getPackageManager.ts b/src/helpers/getPackageManager.ts new file mode 100644 index 0000000..8125e08 --- /dev/null +++ b/src/helpers/getPackageManager.ts @@ -0,0 +1,19 @@ +import { PackageManager } from '@/types'; + +export function getPackageManager(): PackageManager { + const userAgent = process.env.npm_config_user_agent || ''; + + if (userAgent.startsWith('yarn')) { + return 'yarn'; + } + + if (userAgent.startsWith('pnpm')) { + return 'pnpm'; + } + + if (userAgent.startsWith('bun')) { + return 'bun'; + } + + return 'npm'; +} diff --git a/src/helpers/handleFilesByLanguage.ts b/src/helpers/handleFilesByLanguage.ts new file mode 100644 index 0000000..024340b --- /dev/null +++ b/src/helpers/handleFilesByLanguage.ts @@ -0,0 +1,42 @@ +import { CreateOptions } from '@/types'; + +import { + handleDotnet, + handleGo, + handleJava, + handleNodeJs, + handlePhp, + handlePython, + handleRuby, +} from './languageHandlers'; + +interface HandleFilesByLanguageProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleFilesByLanguage({ + createOptions, + root, +}: HandleFilesByLanguageProps) { + const { language } = createOptions; + + switch (language?.value) { + case 'nodejs': + return handleNodeJs({ createOptions, root }); + case 'java': + return handleJava({ createOptions, root }); + case 'python': + return handlePython({ createOptions, root }); + case 'dotnet': + return handleDotnet({ createOptions, root }); + case 'php': + return handlePhp({ createOptions, root }); + case 'ruby': + return handleRuby({ createOptions, root }); + case 'go': + return handleGo({ createOptions, root }); + default: + return; + } +} diff --git a/src/helpers/howToRunTests.ts b/src/helpers/howToRunTests.ts new file mode 100644 index 0000000..75b3f14 --- /dev/null +++ b/src/helpers/howToRunTests.ts @@ -0,0 +1,74 @@ +import pc from 'picocolors'; + +import { Framework, Language, PackageManager } from '@/types'; + +interface HowToRunTestsProps { + cdpath: string; + framework: Framework | null; + language: Language | null; + packageManager: PackageManager | null; + installDependencies: boolean; +} + +export function howToRunTests({ + cdpath, + framework, + language, + packageManager, + installDependencies, +}: HowToRunTestsProps) { + console.log('\nTo run your tests, type:'); + console.log(pc.cyan(`\n cd`), cdpath); + + switch (language?.value) { + case 'nodejs': + const useYarn = packageManager === 'yarn'; + + if (!installDependencies) { + console.log(pc.cyan(` ${packageManager} install`)); + } + + console.log(pc.cyan(` ${packageManager} ${useYarn ? '' : 'run '}test`)); + break; + case 'dotnet': + console.log(pc.cyan(` dotnet test`)); + break; + case 'java': + console.log(pc.cyan(` mvn clean test`)); + break; + case 'python': + if (!installDependencies) { + console.log(pc.cyan(` pip install -r requirements.txt`)); + } + + switch (framework?.value) { + case 'robotframework': + console.log(pc.cyan(` robot tests`)); + break; + case 'selenium': + console.log(pc.cyan(` python -m unittest discover`)); + break; + } + + break; + case 'php': + if (!installDependencies) { + console.log(pc.cyan(` composer update`)); + } + + console.log(pc.cyan(` composer run test`)); + break; + case 'ruby': + if (!installDependencies) { + console.log(pc.cyan(` bundle install`)); + } + + console.log(pc.cyan(` rake`)); + break; + case 'go': + console.log(pc.cyan(` go test -v`)); + break; + default: + break; + } +} diff --git a/src/helpers/index.ts b/src/helpers/index.ts new file mode 100644 index 0000000..8743c59 --- /dev/null +++ b/src/helpers/index.ts @@ -0,0 +1,11 @@ +export { getPackageManager } from './getPackageManager'; +export { isFolderEmpty } from './isFolderEmpty'; +export { isWriteable } from './isWriteable'; +export { exit } from './exit'; +export { copy } from './copy'; +export { modifyPackageJson } from './modifyPackageJson'; +export { install } from './install'; +export { handleFilesByLanguage } from './handleFilesByLanguage'; +export { checkIfInstalled } from './checkIfInstalled'; +export { howToRunTests } from './howToRunTests'; +export { modifyComposerJson } from './modifyComposerJson'; diff --git a/src/helpers/install.ts b/src/helpers/install.ts new file mode 100644 index 0000000..74f5d48 --- /dev/null +++ b/src/helpers/install.ts @@ -0,0 +1,48 @@ +import spawn from 'cross-spawn'; + +import { PackageManager } from '@/types'; + +interface InstallProps { + packageManager: PackageManager | null; +} + +export async function install({ packageManager }: InstallProps): Promise { + if (!packageManager) { + return; + } + + const args: string[] = []; + + switch (packageManager) { + case 'bun': + case 'npm': + case 'pnpm': + case 'yarn': + case 'bundle': + args.push('install'); + break; + case 'pip': + args.push('install', '-r', 'requirements.txt'); + break; + case 'composer': + args.push('update'); + break; + default: + break; + } + + return new Promise((resolve, reject) => { + const child = spawn(packageManager, args, { + stdio: 'ignore', + }); + + child.on('close', (code: number) => { + if (code !== 0) { + reject({ command: `${packageManager} ${args.join(' ')}` }); + return; + } + + resolve(); + }); + }); +} diff --git a/src/helpers/isFolderEmpty.ts b/src/helpers/isFolderEmpty.ts new file mode 100644 index 0000000..edea631 --- /dev/null +++ b/src/helpers/isFolderEmpty.ts @@ -0,0 +1,17 @@ +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; +import { exit } from './exit'; + +interface IsFolderEmptyProps { + root: string; +} + +export async function isFolderEmpty({ root }: IsFolderEmptyProps) { + const files = await fsExtra.readdir(root); + + if (files.length > 0) { + console.error(`${pc.red(pc.bold('\nRoot folder must be empty'))}`); + exit(1); + } +} diff --git a/src/helpers/isWriteable.ts b/src/helpers/isWriteable.ts new file mode 100644 index 0000000..777fcc0 --- /dev/null +++ b/src/helpers/isWriteable.ts @@ -0,0 +1,20 @@ +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; + +import { exit } from './exit'; + +interface IsWriteableProps { + root: string; +} + +export async function isWriteable({ root }: IsWriteableProps) { + try { + await fsExtra.access(root, fsExtra.constants.W_OK); + } catch (err) { + console.error( + `${pc.red(pc.bold('\nYou dont have permission to write to this folder'))}` + ); + exit(1); + } +} diff --git a/src/helpers/languageHandlers/handleDotnet.ts b/src/helpers/languageHandlers/handleDotnet.ts new file mode 100644 index 0000000..d603914 --- /dev/null +++ b/src/helpers/languageHandlers/handleDotnet.ts @@ -0,0 +1,22 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; +import { CreateOptions } from '@/types'; + +interface HandleDotNetProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleDotnet({ createOptions, root }: HandleDotNetProps) { + const { apiKey, serverId } = createOptions; + + const secrets = `{ + "Secrets": { + "MailosaurApiKey": "${apiKey}", + "MailosaurServerId": "${serverId}", + "MailosaurPhoneNumber": "" + } +}`; + + await fsExtra.writeFile(path.join(root, 'appsettings.Testing.json'), secrets); +} diff --git a/src/helpers/languageHandlers/handleGo.ts b/src/helpers/languageHandlers/handleGo.ts new file mode 100644 index 0000000..3327807 --- /dev/null +++ b/src/helpers/languageHandlers/handleGo.ts @@ -0,0 +1,20 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import { CreateOptions } from '@/types'; + +interface HandleGoProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleGo({ createOptions, root }: HandleGoProps) { + const { apiKey, serverId } = createOptions; + + const envContent = `MAILOSAUR_API_KEY=${apiKey} +MAILOSAUR_SERVER_ID=${serverId} +MAILOSAUR_PHONE_NUMBER= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); +} diff --git a/src/helpers/languageHandlers/handleJava.ts b/src/helpers/languageHandlers/handleJava.ts new file mode 100644 index 0000000..099ebf1 --- /dev/null +++ b/src/helpers/languageHandlers/handleJava.ts @@ -0,0 +1,20 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import { CreateOptions } from '@/types'; + +interface HandleJavaProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleJava({ createOptions, root }: HandleJavaProps) { + const { apiKey, serverId } = createOptions; + + const envContent = `mailosaurApiKey=${apiKey} +mailosaurServerId=${serverId} +mailosaurPhoneNumber= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); +} diff --git a/src/helpers/languageHandlers/handleNodeJs.ts b/src/helpers/languageHandlers/handleNodeJs.ts new file mode 100644 index 0000000..5f8e509 --- /dev/null +++ b/src/helpers/languageHandlers/handleNodeJs.ts @@ -0,0 +1,41 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; + +import { CreateOptions } from '@/types'; + +import { install } from '../install'; +import { modifyPackageJson } from '../modifyPackageJson'; + +interface HandleNodeJsProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleNodeJs({ createOptions, root }: HandleNodeJsProps) { + const { apiKey, serverId, projectName, installDependencies, packageManager } = + createOptions; + + const envContent = `MAILOSAUR_API_KEY=${apiKey} +MAILOSAUR_SERVER_ID=${serverId} +MAILOSAUR_PHONE_NUMBER= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); + + const packageJson = await modifyPackageJson(root, projectName); + + if (!installDependencies) { + return; + } + + console.log(pc.cyan(pc.bold(`\nUsing ${packageManager}`))); + console.log('\nInstalling dependencies:\n'); + + for (const dependency in packageJson.dependencies) { + console.log(` - ${pc.cyan(dependency)}`); + } + + await install({ packageManager }); +} diff --git a/src/helpers/languageHandlers/handlePhp.ts b/src/helpers/languageHandlers/handlePhp.ts new file mode 100644 index 0000000..f814fa4 --- /dev/null +++ b/src/helpers/languageHandlers/handlePhp.ts @@ -0,0 +1,38 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; + +import { CreateOptions } from '@/types'; + +import { install } from '../install'; +import { modifyComposerJson } from '../modifyComposerJson'; + +interface HandlePhpProps { + createOptions: CreateOptions; + root: string; +} + +export async function handlePhp({ createOptions, root }: HandlePhpProps) { + const { apiKey, serverId, projectName, installDependencies } = createOptions; + + const envContent = `MAILOSAUR_API_KEY=${apiKey} +MAILOSAUR_SERVER_ID=${serverId} +MAILOSAUR_PHONE_NUMBER= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); + + const composerJson = await modifyComposerJson(root, projectName); + + if (!installDependencies) return; + + console.log(pc.cyan(pc.bold('\nUsing composer'))); + console.log('\nInstalling requires:\n'); + + for (const require in composerJson.require) { + console.log(` - ${pc.cyan(require)}`); + } + + await install({ packageManager: 'composer' }); +} diff --git a/src/helpers/languageHandlers/handlePython.ts b/src/helpers/languageHandlers/handlePython.ts new file mode 100644 index 0000000..b1b73ff --- /dev/null +++ b/src/helpers/languageHandlers/handlePython.ts @@ -0,0 +1,44 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; + +import { CreateOptions } from '@/types'; + +import { install } from '../install'; + +interface HandlePythonProps { + createOptions: CreateOptions; + root: string; +} + +export async function handlePython({ createOptions, root }: HandlePythonProps) { + const { apiKey, installDependencies, serverId } = createOptions; + + const envContent = `MAILOSAUR_API_KEY=${apiKey} +MAILOSAUR_SERVER_ID=${serverId} +MAILOSAUR_PHONE_NUMBER= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); + + if (!installDependencies) { + return; + } + + console.log(pc.cyan(pc.bold(`\nUsing pip`))); + console.log('\nInstalling requirements:\n'); + + const requirementsFilePath = path.join(root, 'requirements.txt'); + + const requirements = fsExtra + .readFileSync(requirementsFilePath, 'utf-8') + .split('\n') + .filter(Boolean); + + for (const requirement of requirements) { + console.log(` - ${pc.cyan(requirement.split('==')[0])}`); + } + + await install({ packageManager: 'pip' }); +} diff --git a/src/helpers/languageHandlers/handleRuby.ts b/src/helpers/languageHandlers/handleRuby.ts new file mode 100644 index 0000000..48ba670 --- /dev/null +++ b/src/helpers/languageHandlers/handleRuby.ts @@ -0,0 +1,51 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +import pc from 'picocolors'; + +import { CreateOptions } from '@/types'; + +import { install } from '../install'; + +interface HandleRubyProps { + createOptions: CreateOptions; + root: string; +} + +export async function handleRuby({ createOptions, root }: HandleRubyProps) { + const { apiKey, installDependencies, serverId } = createOptions; + + const envContent = `MAILOSAUR_API_KEY=${apiKey} +MAILOSAUR_SERVER_ID=${serverId} +MAILOSAUR_PHONE_NUMBER= +`; + + await fsExtra.writeFile(path.join(root, '.env'), envContent); + + if (!installDependencies) { + return; + } + + console.log(pc.cyan(pc.bold(`\nUsing bundler`))); + console.log('\nInstalling gems:\n'); + + const gemFilePath = path.join(root, 'Gemfile'); + + const gems = fsExtra + .readFileSync(gemFilePath, 'utf-8') + .split('\n') + .filter(Boolean); + + const gemRegex = /^gem ['"]([^'"]+)['"],\s*['"]([^'"]+)['"]/; + + for (const gem of gems) { + const match = gemRegex.exec(gem); + + if (match) { + const gemName = match[1]; + console.log(` - ${pc.cyan(gemName)}`); + } + } + + await install({ packageManager: 'bundle' }); +} diff --git a/src/helpers/languageHandlers/index.ts b/src/helpers/languageHandlers/index.ts new file mode 100644 index 0000000..0a86d36 --- /dev/null +++ b/src/helpers/languageHandlers/index.ts @@ -0,0 +1,7 @@ +export { handleNodeJs } from './handleNodeJs'; +export { handleDotnet } from './handleDotnet'; +export { handleJava } from './handleJava'; +export { handlePython } from './handlePython'; +export { handlePhp } from './handlePhp'; +export { handleRuby } from './handleRuby'; +export { handleGo } from './handleGo'; diff --git a/src/helpers/modifyComposerJson.ts b/src/helpers/modifyComposerJson.ts new file mode 100644 index 0000000..31ddd2c --- /dev/null +++ b/src/helpers/modifyComposerJson.ts @@ -0,0 +1,18 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +export async function modifyComposerJson(root: string, newName: string) { + const composerJsonPath = path.join(root, 'composer.json'); + + const composerJsonString = await fsExtra.readFile(composerJsonPath, 'utf8'); + const composerJson = JSON.parse(composerJsonString); + + composerJson.name = `mailosaur-example/${newName}`; + + await fsExtra.writeFile( + composerJsonPath, + JSON.stringify(composerJson, null, 2) + ); + + return composerJson; +} diff --git a/src/helpers/modifyPackageJson.ts b/src/helpers/modifyPackageJson.ts new file mode 100644 index 0000000..486bcd3 --- /dev/null +++ b/src/helpers/modifyPackageJson.ts @@ -0,0 +1,18 @@ +import path from 'path'; +import fsExtra from 'fs-extra'; + +export async function modifyPackageJson(root: string, newName: string) { + const packageJsonPath = path.join(root, 'package.json'); + + const packageJsonString = await fsExtra.readFile(packageJsonPath, 'utf8'); + const packageJson = JSON.parse(packageJsonString); + + packageJson.name = newName; + + await fsExtra.writeFile( + packageJsonPath, + JSON.stringify(packageJson, null, 2) + ); + + return packageJson; +} diff --git a/src/index.ts b/src/index.ts new file mode 100755 index 0000000..44028ae --- /dev/null +++ b/src/index.ts @@ -0,0 +1,63 @@ +#!/usr/bin/env node + +import { CreateOptions } from '@/types'; +import { checkIfInstalled, getPackageManager } from '@/helpers'; +import { + apiKeyInput, + frameworkInput, + getProjectPath, + installDependenciesInput, + languageInput, + projectNameInput, + serverIdInput, +} from '@/inputs'; + +import { createTests } from './create-tests'; + +const handleSigTerm = () => process.exit(0); + +process.on('SIGINT', handleSigTerm); +process.on('SIGTERM', handleSigTerm); + +async function main() { + let isServerApiKey = false; + + const createOptions: CreateOptions = { + packageManager: null, + projectName: '', + projectPath: '', + framework: null, + language: null, + apiKey: '', + serverId: '', + installDependencies: false, + }; + + createOptions.packageManager = getPackageManager(); + + createOptions.projectName = await projectNameInput(); + + createOptions.projectPath = await getProjectPath(createOptions.projectName); + + createOptions.framework = await frameworkInput(); + + createOptions.language = await languageInput(createOptions.framework); + + createOptions.language.requiredLibraries?.forEach((library) => { + checkIfInstalled(library); + }); + + createOptions.apiKey = await apiKeyInput(isServerApiKey); + + createOptions.serverId = await serverIdInput(); + + if (createOptions.language?.installDependencies) { + createOptions.installDependencies = await installDependenciesInput( + createOptions.language + ); + } + + await createTests(createOptions); +} + +main(); diff --git a/src/inputs/apiKeyInput.ts b/src/inputs/apiKeyInput.ts new file mode 100644 index 0000000..d24044c --- /dev/null +++ b/src/inputs/apiKeyInput.ts @@ -0,0 +1,51 @@ +import prompts from 'prompts'; +import pc from 'picocolors'; + +import { exit } from '@/helpers'; + +export async function apiKeyInput(isServerApiKey: boolean): Promise { + console.log(); // Creates space + + const enteredApiKey = await prompts( + { + type: 'password', + name: 'value', + message: 'Please enter your api key:', + validate: async (value) => { + const encodedApiKey = Buffer.from(`key:${value}`).toString('base64'); + + const res = await fetch('https://mailosaur.com/api/servers', { + method: 'GET', + headers: { + Authorization: `Basic ${encodedApiKey}`, + 'Content-Type': 'application/json', + }, + }); + + if (res.status === 200) { + return true; + } + + if (res.status === 403) { + isServerApiKey = true; + return true; + } + + return 'Invalid api key'; + }, + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + if (isServerApiKey) { + console.log( + pc.yellow(pc.bold('\nApi key is a server api key (some tests wont work)')) + ); + } + + return enteredApiKey.value; +} diff --git a/src/inputs/frameworkInput.ts b/src/inputs/frameworkInput.ts new file mode 100644 index 0000000..23ed6c5 --- /dev/null +++ b/src/inputs/frameworkInput.ts @@ -0,0 +1,35 @@ +import prompts from 'prompts'; + +import { exit } from '@/helpers'; +import { frameworks } from '@/options'; +import { Framework, Frameworks } from '@/types'; + +export async function frameworkInput(): Promise { + console.log(); // Creates space + + const frameworkKeys = Object.keys(frameworks).map((framework) => framework); + + const enteredFramework = await prompts( + { + type: 'select', + name: 'value', + message: 'Choose your framework', + choices: frameworkKeys.map((framework) => ({ + title: frameworks[framework as Frameworks].name, + value: frameworks[framework as Frameworks].value, + })), + initial: 0, + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + if (!enteredFramework.value) { + return frameworks.other; + } + + return frameworks[enteredFramework.value as Frameworks]; +} diff --git a/src/inputs/getProjectPath.ts b/src/inputs/getProjectPath.ts new file mode 100644 index 0000000..71545d6 --- /dev/null +++ b/src/inputs/getProjectPath.ts @@ -0,0 +1,43 @@ +import fs from 'fs'; +import path, { dirname } from 'path'; + +import pc from 'picocolors'; +import validate from 'validate-npm-package-name'; + +import { exit, isFolderEmpty, isWriteable } from '@/helpers'; + +export async function getProjectPath(projectName: string): Promise { + const validation = validate(projectName); + + if (validation.errors) { + console.error( + `Could not create a project called ${pc.red( + `"${projectName}"` + )} because of npm naming restrictions:` + ); + + validation.errors.forEach((p) => + console.error(`${pc.red(pc.bold('*'))} ${p}`) + ); + + exit(1); + } + + const resolvedProjectPath = path.resolve(projectName); + + const root = path.resolve(resolvedProjectPath); + + const folderExists = fs.existsSync(root); + + if (folderExists) { + console.error(`${pc.red(pc.bold('\nFolder already exists'))}`); + exit(1); + } + + //! ADD THIS BACK WHEN NOT LOCALLY TESTING + //! await isFolderEmpty({ root: dirname(root) }); + + await isWriteable({ root: dirname(root) }); + + return root; +} diff --git a/src/inputs/index.ts b/src/inputs/index.ts new file mode 100644 index 0000000..5c0e486 --- /dev/null +++ b/src/inputs/index.ts @@ -0,0 +1,7 @@ +export { apiKeyInput } from './apiKeyInput'; +export { projectNameInput } from './projectNameInput'; +export { getProjectPath } from './getProjectPath'; +export { frameworkInput } from './frameworkInput'; +export { languageInput } from './languageInput'; +export { serverIdInput } from './serverIdInput'; +export { installDependenciesInput } from './installDependenciesInput'; diff --git a/src/inputs/installDependenciesInput.ts b/src/inputs/installDependenciesInput.ts new file mode 100644 index 0000000..c561a5b --- /dev/null +++ b/src/inputs/installDependenciesInput.ts @@ -0,0 +1,45 @@ +import prompts from 'prompts'; + +import { exit } from '@/helpers'; +import { Language } from '@/types'; + +export async function installDependenciesInput(language: Language) { + console.log(); // Creates space + + let dependencyName = ''; + + switch (language.value) { + case 'nodejs': + dependencyName = 'required dependencies'; + break; + case 'python': + dependencyName = 'requirements'; + break; + case 'ruby': + dependencyName = 'required gems'; + break; + case 'php': + dependencyName = 'requirements'; + break; + default: + break; + } + + const enteredServerId = await prompts( + { + type: 'toggle', + name: 'value', + message: `Install ${dependencyName}?`, + initial: true, + active: 'Yes', + inactive: 'No', + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + return enteredServerId.value; +} diff --git a/src/inputs/languageInput.ts b/src/inputs/languageInput.ts new file mode 100644 index 0000000..4e7b4f2 --- /dev/null +++ b/src/inputs/languageInput.ts @@ -0,0 +1,35 @@ +import prompts from 'prompts'; + +import { exit } from '@/helpers'; +import { languages } from '@/options'; +import { Framework, Language, Languages } from '@/types'; + +export async function languageInput( + framework: Framework | null +): Promise { + if (framework?.value && framework?.languages.length === 1) { + return framework.languages[0]; + } + + console.log(); // Creates space + + const enteredFramework = await prompts( + { + type: 'select', + name: 'value', + message: 'Choose your language', + choices: framework?.languages.map((language) => ({ + title: language.name, + value: language.value, + })), + initial: 0, + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + return languages[enteredFramework.value as Languages]; +} diff --git a/src/inputs/projectNameInput.ts b/src/inputs/projectNameInput.ts new file mode 100644 index 0000000..5df6cd1 --- /dev/null +++ b/src/inputs/projectNameInput.ts @@ -0,0 +1,41 @@ +import path from 'path'; + +import prompts from 'prompts'; +import validate from 'validate-npm-package-name'; + +import { exit } from '@/helpers'; + +export async function projectNameInput(): Promise { + console.log(); // Creates space + + const enteredProjectName = await prompts( + { + type: 'text', + name: 'value', + message: 'What is your project named?', + initial: 'mailosaur-tests', + validate: (name) => { + const validation = validate(path.basename(path.resolve(name))); + + if (!validation.errors) { + return true; + } + + return 'Invalid project name: ' + validation.errors[0]; + }, + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + const projectPath = enteredProjectName.value; + + const resolvedProjectPath = path.resolve(projectPath); + + const projectName = path.basename(resolvedProjectPath); + + return projectName; +} diff --git a/src/inputs/serverIdInput.ts b/src/inputs/serverIdInput.ts new file mode 100644 index 0000000..8a6df48 --- /dev/null +++ b/src/inputs/serverIdInput.ts @@ -0,0 +1,29 @@ +import prompts from 'prompts'; + +import { exit } from '@/helpers'; + +export async function serverIdInput(): Promise { + console.log(); // Creates space + + const enteredServerId = await prompts( + { + type: 'text', + name: 'value', + message: 'Please enter your server id:', + validate: async (value: string) => { + if (value.length === 8) { + return true; + } + + return 'Invalid server id'; + }, + }, + { + onCancel: () => { + exit(0); + }, + } + ); + + return enteredServerId.value; +} diff --git a/src/options/frameworks.ts b/src/options/frameworks.ts new file mode 100644 index 0000000..476bd3b --- /dev/null +++ b/src/options/frameworks.ts @@ -0,0 +1,61 @@ +import { Framework, Frameworks } from '@/types'; + +import { languages } from './languages'; + +const cypress: Framework = { + name: 'Cypress', + value: 'cypress', + languages: [languages.nodejs], +}; + +const playwright: Framework = { + name: 'Playwright', + value: 'playwright', + languages: [languages.nodejs, languages.dotnet], +}; + +const robotframework: Framework = { + name: 'Robot Framework', + value: 'robotframework', + languages: [languages.python], +}; + +const selenium: Framework = { + name: 'Selenium', + value: 'selenium', + languages: [ + languages.dotnet, + languages.java, + languages.python, + languages.ruby, + ], +}; + +const webdriverio: Framework = { + name: 'WebdriverIO', + value: 'webdriverio', + languages: [languages.nodejs], +}; + +const other: Framework = { + name: 'Other (Select language)', + value: null, + languages: [ + languages.nodejs, + languages.dotnet, + languages.java, + languages.python, + languages.php, + languages.ruby, + languages.go, + ], +}; + +export const frameworks: Record = { + cypress, + playwright, + robotframework, + selenium, + webdriverio, + other, +}; diff --git a/src/options/index.ts b/src/options/index.ts new file mode 100644 index 0000000..d2c5972 --- /dev/null +++ b/src/options/index.ts @@ -0,0 +1,2 @@ +export { frameworks } from './frameworks'; +export { languages } from './languages'; diff --git a/src/options/languages.ts b/src/options/languages.ts new file mode 100644 index 0000000..378bc5f --- /dev/null +++ b/src/options/languages.ts @@ -0,0 +1,63 @@ +import { Language, Languages } from '@/types'; + +const nodejs: Language = { + name: 'Node.js', + value: 'nodejs', + installDependencies: true, + defaultFramework: 'playwright', + requiredLibraries: ['node'], +}; + +const dotnet: Language = { + name: '.NET', + value: 'dotnet', + installDependencies: false, + defaultFramework: 'selenium', +}; + +const java: Language = { + name: 'Java', + value: 'java', + installDependencies: false, + defaultFramework: 'selenium', +}; + +const python: Language = { + name: 'Python', + value: 'python', + installDependencies: true, + defaultFramework: 'selenium', + requiredLibraries: ['python', 'pip'], +}; + +const php: Language = { + name: 'PHP', + value: 'php', + installDependencies: true, + requiredLibraries: ['php', 'composer'], +}; + +const ruby: Language = { + name: 'Ruby', + value: 'ruby', + installDependencies: true, + defaultFramework: 'selenium', + requiredLibraries: ['ruby'], +}; + +const go: Language = { + name: 'Go', + value: 'go', + installDependencies: false, + requiredLibraries: ['go'], +}; + +export const languages: Record = { + nodejs, + dotnet, + java, + python, + php, + ruby, + go, +}; diff --git a/src/scaffolding.ts b/src/scaffolding.ts new file mode 100644 index 0000000..a77825e --- /dev/null +++ b/src/scaffolding.ts @@ -0,0 +1,50 @@ +import path from 'path'; + +import { CreateOptions, Frameworks } from '@/types'; +import { copy, handleFilesByLanguage } from '@/helpers'; +import { frameworks } from '@/options'; + +interface ScaffoldSampleProps { + createOptions: CreateOptions; + root: string; +} + +const examplesFolderName = 'examples'; + +export async function scaffoldSample({ + createOptions, + root, +}: ScaffoldSampleProps) { + const { framework, language } = createOptions; + + let examplePath = ''; + + if (!framework?.value) { + examplePath = path.join( + __dirname, + examplesFolderName, + language?.defaultFramework || '', + frameworks[language?.defaultFramework as Frameworks]?.languages.length > + 1 || true + ? language?.value || '' + : '' + ); + } else if (framework.languages.length === 1) { + examplePath = path.join( + __dirname, + examplesFolderName, + framework?.value || '' + ); + } else { + examplePath = path.join( + __dirname, + examplesFolderName, + framework?.value || '', + language?.value || '' + ); + } + + await copy(examplePath, root); + + await handleFilesByLanguage({ createOptions, root }); +} diff --git a/src/types/createOptions.ts b/src/types/createOptions.ts new file mode 100644 index 0000000..5a2dd2f --- /dev/null +++ b/src/types/createOptions.ts @@ -0,0 +1,14 @@ +import { Framework } from './frameworks'; +import { Language } from './languages'; +import { PackageManager } from './packageManager'; + +export type CreateOptions = { + packageManager: PackageManager | null; + projectName: string; + projectPath: string; + framework: Framework | null; + language: Language | null; + apiKey: string; + serverId: string; + installDependencies: boolean; +}; diff --git a/src/types/frameworks.ts b/src/types/frameworks.ts new file mode 100644 index 0000000..c6327dc --- /dev/null +++ b/src/types/frameworks.ts @@ -0,0 +1,15 @@ +import { Language } from './languages'; + +export interface Framework { + name: string; + value: string | null; + languages: Language[]; +} + +export type Frameworks = + | 'cypress' + | 'playwright' + | 'robotframework' + | 'selenium' + | 'webdriverio' + | 'other'; diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..00e743b --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,5 @@ +export { type PackageManager } from './packageManager'; +export { type CreateOptions } from './createOptions'; +export { type Language, type Languages } from './languages'; +export { type Framework, type Frameworks } from './frameworks'; +export { type Libraries } from './libraries'; diff --git a/src/types/languages.ts b/src/types/languages.ts new file mode 100644 index 0000000..6ec6898 --- /dev/null +++ b/src/types/languages.ts @@ -0,0 +1,19 @@ +import { Frameworks } from './frameworks'; +import { Libraries } from './libraries'; + +export interface Language { + name: string; + value: Languages; + installDependencies: boolean; + defaultFramework?: Frameworks; + requiredLibraries?: Libraries[]; +} + +export type Languages = + | 'nodejs' + | 'dotnet' + | 'java' + | 'python' + | 'php' + | 'ruby' + | 'go'; diff --git a/src/types/libraries.ts b/src/types/libraries.ts new file mode 100644 index 0000000..743a141 --- /dev/null +++ b/src/types/libraries.ts @@ -0,0 +1,8 @@ +export type Libraries = + | 'node' + | 'python' + | 'pip' + | 'php' + | 'composer' + | 'ruby' + | 'go'; diff --git a/src/types/packageManager.ts b/src/types/packageManager.ts new file mode 100644 index 0000000..2daf208 --- /dev/null +++ b/src/types/packageManager.ts @@ -0,0 +1,8 @@ +export type PackageManager = + | 'npm' + | 'pnpm' + | 'yarn' + | 'bun' + | 'pip' + | 'composer' + | 'bundle'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c66d707 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "strict": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + "noImplicitAny": true, + "esModuleInterop": true, + "strictNullChecks": true, + "target": "ES2022", + "moduleResolution": "Node10", + "module": "CommonJS", + "declaration": true, + "isolatedModules": true, + "noEmit": true, + "outDir": "dist" + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..9117b39 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,26 @@ +import { join } from 'path'; +import fsExtra from 'fs-extra'; +import { defineConfig } from 'tsup'; + +export default defineConfig({ + format: ['cjs', 'esm'], + entry: ['./src/index.ts'], + dts: true, + shims: true, + skipNodeModulesBundle: true, + clean: true, + onSuccess: async () => { + const sourceDir = './src/examples'; + const targetDir = './dist/examples'; + + await fsExtra.copy(sourceDir, targetDir); + + const indexPath = join(targetDir, 'index.ts'); + const binPath = join(targetDir, 'xunit/bin'); + const objPath = join(targetDir, 'xunit/obj'); + + await fsExtra.remove(indexPath); + await fsExtra.remove(binPath); + await fsExtra.remove(objPath); + }, +});