From 6f539ce45756edbce86f541c8068ba389e1afb50 Mon Sep 17 00:00:00 2001 From: Stephen Hanson Date: Fri, 3 Nov 2023 11:18:45 -0500 Subject: [PATCH] Add default 'create' command to create new app (#16) * Add default 'create' command to create new app * Print welcome messages, start test --- __mocks__/child_process.js | 5 + __mocks__/fs-extra.js | 3 + __mocks__/process.js | 3 + package.json | 20 +- src/cli.ts | 16 +- src/commands/__tests__/createApp.test.ts | 27 ++ src/commands/__tests__/typescript.test.ts | 6 +- src/commands/createApp.ts | 60 ++++ src/commands/eslint.ts | 12 +- src/commands/scaffold.ts | 20 ++ .../src/components/buttons/PrimaryButton.tsx | 33 ++ .../templates/scaffold/src/screens/.keep | 0 .../templates/scaffold/src/test/.keep | 0 .../templates/scaffold/src/util/hooks/.keep | 0 src/util/addDependency.ts | 6 +- src/util/formatFile.ts | 4 +- src/util/print/__tests__/printWelcome.test.ts | 8 + src/util/print/printWelcome.ts | 9 + tsconfig.json | 3 +- vitest.config.ts | 1 + vitest.setup.js | 4 + yarn.lock | 288 ++++++++++-------- 22 files changed, 379 insertions(+), 149 deletions(-) create mode 100644 __mocks__/child_process.js create mode 100644 __mocks__/process.js create mode 100644 src/commands/__tests__/createApp.test.ts create mode 100644 src/commands/createApp.ts create mode 100644 src/commands/scaffold.ts create mode 100644 src/commands/templates/scaffold/src/components/buttons/PrimaryButton.tsx create mode 100644 src/commands/templates/scaffold/src/screens/.keep create mode 100644 src/commands/templates/scaffold/src/test/.keep create mode 100644 src/commands/templates/scaffold/src/util/hooks/.keep create mode 100644 src/util/print/__tests__/printWelcome.test.ts create mode 100644 src/util/print/printWelcome.ts create mode 100644 vitest.setup.js diff --git a/__mocks__/child_process.js b/__mocks__/child_process.js new file mode 100644 index 0000000..07bb58e --- /dev/null +++ b/__mocks__/child_process.js @@ -0,0 +1,5 @@ +import { vi } from 'vitest'; + +export const spawnSync = vi.fn(); +export const execSync = vi.fn(); +export const exec = vi.fn(); diff --git a/__mocks__/fs-extra.js b/__mocks__/fs-extra.js index bfb7b04..7c7802e 100644 --- a/__mocks__/fs-extra.js +++ b/__mocks__/fs-extra.js @@ -1,10 +1,13 @@ import actualfs from 'fs-extra'; import { fs } from 'memfs'; +import { vi } from 'vitest'; const DONT_MOCK_PATTERNS = ['templates/']; export default { ...fs.promises, + // todo: build actual mock + copySync: vi.fn(), exists(path) { return new Promise((resolve) => { fs.exists(path, (exists) => resolve(exists)); diff --git a/__mocks__/process.js b/__mocks__/process.js new file mode 100644 index 0000000..c5da8c1 --- /dev/null +++ b/__mocks__/process.js @@ -0,0 +1,3 @@ +export default { + chdir: vi.fn(), +}; diff --git a/package.json b/package.json index 7134d74..ffee176 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "lint:prettier": "prettier --check '**/*' --ignore-unknown", "lint:types": "tsc", "fix:prettier": "prettier --write '**/*' --ignore-unknown", - "test": "vitest watch", - "test:run": "test run", + "test": "vitest", + "test:run": "vitest run", "test:all": "yarn lint && yarn test:run" }, "bin": { @@ -21,13 +21,13 @@ "author": "thoughtbot, Inc.", "license": "MIT", "dependencies": { + "@inquirer/prompts": "^3.2.0", "@thoughtbot/eslint-config": "^1.0.2", "chalk": "^5.2.0", "commander": "^10.0.1", "eslint": "^8.45.0", "eta": "^2.1.1", "fs-extra": "^11.1.1", - "inquirer": "^9.2.0", "ora": "^6.3.0", "prettier": "^3.0.1", "ts-node": "^10.9.1" @@ -47,14 +47,16 @@ "@thoughtbot/eslint-config/prettier", "@thoughtbot/eslint-config/typescript" ], - "rules": { - "no-console": "off", - "import/order": "off" - }, "ignorePatterns": [ + "src/commands/templates", "__mocks__/**/*.js", "bin/belt.js", - "/build" - ] + "/build", + "vitest.setup.js" + ], + "rules": { + "no-console": "off", + "import/order": "off" + } } } diff --git a/src/cli.ts b/src/cli.ts index e656e14..2310c13 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,5 +1,6 @@ import { program } from 'commander'; import buildAction from './util/buildAction'; +import printWelcome from './util/print/printWelcome'; export default function runCli() { program @@ -7,7 +8,19 @@ export default function runCli() { .description( 'Perform React Native and Expo setup and redundant tasks without your pants falling down!', ) + .showHelpAfterError(); + program + .command('create', { isDefault: true }) + .description('Create new app') + .argument( + '[appName]', + 'The name of the app and directory it will be created in', + '', + ) + .action(buildAction(import('./commands/createApp'))); + + program .command('eslint') .description('Configure ESLint') .action(buildAction(import('./commands/eslint'))); @@ -22,7 +35,8 @@ export default function runCli() { .description('Install and configure TypeScript') .action(buildAction(import('./commands/typescript'))); - program.showHelpAfterError().parse(); + printWelcome(); + program.parse(); } runCli(); diff --git a/src/commands/__tests__/createApp.test.ts b/src/commands/__tests__/createApp.test.ts new file mode 100644 index 0000000..2a24f31 --- /dev/null +++ b/src/commands/__tests__/createApp.test.ts @@ -0,0 +1,27 @@ +import { confirm } from '@inquirer/prompts'; +import { vol } from 'memfs'; +import { Mock, afterEach, test, vi } from 'vitest'; +import print from '../../util/print'; +import { createApp } from '../createApp'; + +vi.mock('@inquirer/prompts', () => ({ + confirm: vi.fn(), +})); +vi.mock('../../util/addDependency'); +vi.mock('../../util/print', () => ({ default: vi.fn() })); + +afterEach(() => { + vol.reset(); + (print as Mock).mockReset(); +}); + +test("doesn't error", async () => { + (confirm as Mock).mockResolvedValueOnce(true); + vi.spyOn(process, 'chdir').mockImplementation(() => { + const json = { + 'package.json': '{ "dependencies": {}, "devDependencies": {} }', + }; + vol.fromJSON(json, './'); + }); + await createApp('MyApp'); +}); diff --git a/src/commands/__tests__/typescript.test.ts b/src/commands/__tests__/typescript.test.ts index d7865d7..86c371f 100644 --- a/src/commands/__tests__/typescript.test.ts +++ b/src/commands/__tests__/typescript.test.ts @@ -4,12 +4,8 @@ import addDependency from '../../util/addDependency'; import print from '../../util/print'; import addTypescript from '../typescript'; -vi.mock('fs-extra'); vi.mock('../../util/addDependency'); -vi.mock('../../util/print', () => ({ - // __esModule: true, - default: vi.fn(), -})); +vi.mock('../../util/print', () => ({ default: vi.fn() })); afterEach(() => { vol.reset(); diff --git a/src/commands/createApp.ts b/src/commands/createApp.ts new file mode 100644 index 0000000..e5e9bee --- /dev/null +++ b/src/commands/createApp.ts @@ -0,0 +1,60 @@ +import { confirm, input } from '@inquirer/prompts'; +import { execSync, spawnSync } from 'child_process'; +import print from '../util/print'; +import addEslint from './eslint'; +import createScaffold from './scaffold'; +import addTypescript from './typescript'; + +export async function createApp(name: string | undefined) { + const appName = name || (await getAppName()); + await printIntro(); + + spawnSync('npx', ['--yes', 'create-expo-app@latest', appName], { + stdio: 'inherit', + }); + + process.chdir(`./${appName}`); + + await addTypescript(); + execSync('git add .'); + execSync('git commit -m "Add TypeScript"'); + + await addEslint(); + execSync('git add .'); + execSync('git commit -m "Configure ESLint"'); + + await createScaffold(); + execSync('git add .'); + execSync('git commit -m "Add app scaffold"'); +} + +async function getAppName() { + return input({ message: 'What is the name of your app?' }); +} + +/** + * Commander requires this signature to be ...args: unknown[] + * Actual args are: + * ([, , ]) + * or ([, ]) if not passed) + */ +export default function createAppAction(...args: unknown[]) { + // if argument ommitted, args[0] is options + const appNameArg = (args[0] as string[])[0]; + return createApp(appNameArg); +} + +async function printIntro() { + print('πŸ‘– Let’s get started!'); + print(`\nWe will now perform the following tasks: + - Create a new app using the latest create-expo-app + - Add and configure TypeScript + - Add and configure ESLint + - Add and configure Prettier + - Create the project directory structure + `); + + if (!(await confirm({ message: 'Ready to proceed?' }))) { + process.exit(0); + } +} diff --git a/src/commands/eslint.ts b/src/commands/eslint.ts index d9984c9..083efb1 100755 --- a/src/commands/eslint.ts +++ b/src/commands/eslint.ts @@ -1,22 +1,22 @@ -import { log } from 'console'; -import path from 'path'; -import { fileURLToPath, URL } from 'url'; import chalk from 'chalk'; import * as eta from 'eta'; import fs from 'fs-extra'; +import path from 'path'; +import { fileURLToPath, URL } from 'url'; import addDependency from '../util/addDependency'; import getProjectDir from '../util/getProjectDir'; import isEslintConfigured from '../util/isEslintConfigured'; import isPackageInstalled from '../util/isPackageInstalled'; +import print from '../util/print'; import writeFile from '../util/writeFile'; const dirname = fileURLToPath(new URL('.', import.meta.url)); -export default async function runEslint() { +export default async function addEslint() { const projectDir = await getProjectDir(); if (await isEslintConfigured()) { - log('eslint config already exists'); + print('eslint config already exists'); } else { const hasTypeScript = await isPackageInstalled('typescript'); @@ -34,6 +34,6 @@ export default async function runEslint() { await addDependency('@thoughtbot/eslint-config', { dev: true }); - log(chalk.green('πŸŽ‰ ESLint successfully configured')); + print(chalk.green('πŸŽ‰ ESLint successfully configured')); } } diff --git a/src/commands/scaffold.ts b/src/commands/scaffold.ts new file mode 100644 index 0000000..a088c71 --- /dev/null +++ b/src/commands/scaffold.ts @@ -0,0 +1,20 @@ +import chalk from 'chalk'; +import fs from 'fs-extra'; +import path from 'path'; +import { URL, fileURLToPath } from 'url'; +import print from '../util/print'; + +const dirname = fileURLToPath(new URL('.', import.meta.url)); + +export default async function createScaffold() { + print(chalk.bold('πŸ‘– Creating directory structure')); + print(` + src/ + components/ + util/ + hooks/ + test/ + `); + fs.copySync(path.join(dirname, 'templates', 'scaffold', 'src'), './src'); + print('βœ… Created directories'); +} diff --git a/src/commands/templates/scaffold/src/components/buttons/PrimaryButton.tsx b/src/commands/templates/scaffold/src/components/buttons/PrimaryButton.tsx new file mode 100644 index 0000000..52a2eb0 --- /dev/null +++ b/src/commands/templates/scaffold/src/components/buttons/PrimaryButton.tsx @@ -0,0 +1,33 @@ +import { + StyleSheet, + TouchableOpacity, + TouchableOpacityProps, +} from 'react-native'; + +type ButtonProps = TouchableOpacityProps; + +export default function PrimaryButton({ + style, + text, + textStyle, + children, + ...props +}: ButtonProps) { + return ( + + ); +} + +const styles = StyleSheet.create({ + button: { + paddingVertical: 16, + paddingHorizontal: 14, + backgroundColor: '#08f', + borderRadius: 12, + justifyContent: 'center', + }, +}); diff --git a/src/commands/templates/scaffold/src/screens/.keep b/src/commands/templates/scaffold/src/screens/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/templates/scaffold/src/test/.keep b/src/commands/templates/scaffold/src/test/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/templates/scaffold/src/util/hooks/.keep b/src/commands/templates/scaffold/src/util/hooks/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/util/addDependency.ts b/src/util/addDependency.ts index 3a3b89e..dc6706b 100644 --- a/src/util/addDependency.ts +++ b/src/util/addDependency.ts @@ -1,4 +1,4 @@ -import { exec } from 'child_process'; +import { execSync } from 'child_process'; import fs from 'fs-extra'; import * as path from 'path'; import getProjectDir from './getProjectDir'; @@ -7,8 +7,8 @@ export default async function addDependency(deps: string, { dev = false }) { const isYarn = await fs.exists(path.join(await getProjectDir(), 'yarn.lock')); if (isYarn) { - exec(`yarn add ${dev ? '--dev' : ''} ${deps}`); + execSync(`yarn add ${dev ? '--dev' : ''} ${deps}`); } else { - exec(`npm install ${dev ? '--save-dev' : '--save'} ${deps}`); + execSync(`npm install ${dev ? '--save-dev' : '--save'} ${deps}`); } } diff --git a/src/util/formatFile.ts b/src/util/formatFile.ts index 1e5ddd0..2b6e5c1 100644 --- a/src/util/formatFile.ts +++ b/src/util/formatFile.ts @@ -1,5 +1,5 @@ -import { exec } from 'child_process'; +import { execSync } from 'child_process'; export default async function formatFile(filePath: string) { - exec(`npx prettier --write '${filePath}'`); + execSync(`npx prettier --write '${filePath}'`); } diff --git a/src/util/print/__tests__/printWelcome.test.ts b/src/util/print/__tests__/printWelcome.test.ts new file mode 100644 index 0000000..55b7f19 --- /dev/null +++ b/src/util/print/__tests__/printWelcome.test.ts @@ -0,0 +1,8 @@ +import { test, vi } from 'vitest'; +import printWelcome from '../printWelcome'; + +vi.mock('../../print', () => ({ default: vi.fn() })); + +test('doesnt error', () => { + printWelcome(); +}); diff --git a/src/util/print/printWelcome.ts b/src/util/print/printWelcome.ts new file mode 100644 index 0000000..adf849a --- /dev/null +++ b/src/util/print/printWelcome.ts @@ -0,0 +1,9 @@ +import chalk from 'chalk'; +import print from '../print'; + +export default function printWelcome() { + print(chalk.bold('\n\n\tπŸ‘– thoughtbelt πŸ‘–\n')); + print( + 'Perform project setup and redundant tasks\n without your pants falling down!\n\n', + ); +} diff --git a/tsconfig.json b/tsconfig.json index 2593db6..1ed8985 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,6 @@ "esm": true, "experimentalSpecifierResolution": "node" }, - "include": ["./**/*.ts"] + "include": ["./**/*.ts"], + "exclude": ["./src/commands/templates/**/*"] } diff --git a/vitest.config.ts b/vitest.config.ts index d3c9634..ac52938 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,5 +3,6 @@ import { configDefaults, defineConfig } from 'vitest/config'; export default defineConfig({ test: { exclude: [...configDefaults.exclude, 'build/**/*'], + setupFiles: ['./vitest.setup.js'], }, }); diff --git a/vitest.setup.js b/vitest.setup.js new file mode 100644 index 0000000..a90aac7 --- /dev/null +++ b/vitest.setup.js @@ -0,0 +1,4 @@ +import { vi } from 'vitest'; + +vi.mock('child_process'); +vi.mock('fs-extra'); diff --git a/yarn.lock b/yarn.lock index 0fbe209..a1df4e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -182,6 +182,125 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@inquirer/checkbox@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-1.4.0.tgz#9e583188be55f22ed624d2829421a3354d3d8c1a" + integrity sha512-7YcekwCvMTjrgjUursrH6AGZUSPw7gKPMvp0VhM3iq9mL46a7AeCfOTQTW0UPeiIfWmZK8wHyAD6wIhfDyLHpw== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/confirm@^2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-2.0.14.tgz#b87fcdf218d0ce687bd021623e091d3a80744e9e" + integrity sha512-Elzo5VX5lO1q9xy8CChDtDQNVLaucufdZBAM12qdfX1L3NQ+TypnZytGmWDXHBTpBTwuhEuwxNvUw7B0HCURkw== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + chalk "^4.1.2" + +"@inquirer/core@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-5.1.0.tgz#2e3f6abf1dee93eae60cd85a5168c52400f73c9c" + integrity sha512-EVnific72BhMOMo8mElvrYhGFWJZ73X6j0I+fITIPTsdAz6Z9A3w3csKy+XaH87/5QAEIQHR7RSCVXvQpIqNdQ== + dependencies: + "@inquirer/type" "^1.1.5" + "@types/mute-stream" "^0.0.2" + "@types/node" "^20.8.2" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + cli-spinners "^2.9.1" + cli-width "^4.1.0" + figures "^3.2.0" + mute-stream "^1.0.0" + run-async "^3.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + +"@inquirer/editor@^1.2.12": + version "1.2.12" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-1.2.12.tgz#3dfa72253e8a9d915b43f3c8dbc8df85e3c627ff" + integrity sha512-Y7zXQqcglPbbPkx0DPwx6HQFstJR5uex4hoQprjpdxSj8+Bf04+Og6mK/FNxoQbPvoNecegtmMGxDC+hVcMJZA== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + chalk "^4.1.2" + external-editor "^3.1.0" + +"@inquirer/expand@^1.1.13": + version "1.1.13" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-1.1.13.tgz#921d36274c0b143f7bf6cefb42f002be9cd1646f" + integrity sha512-/+7CGCa7iyJIpli0NtukEAjSI7+wGgjYzsByLVSSAk3U696ZlCCP6iPtsWx6d1qfmaMmCzejcjylOj6OAeu4bA== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/input@^1.2.13": + version "1.2.13" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-1.2.13.tgz#27ee5826e2988735a78f50510c9652d2ef29e39a" + integrity sha512-gALuvSpZRYfqygPjlYWodMZ4TXwALvw7Pk4tRFhE1oMN79rLVlg88Z/X6JCUh+uV2qLaxxgbeP+cgPWTvuWsCg== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + chalk "^4.1.2" + +"@inquirer/password@^1.1.13": + version "1.1.13" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-1.1.13.tgz#b7f0a0f7feed90e01630a9df4a14eab09697fcd6" + integrity sha512-6STGbL4Vm6ohE2yDBOSENCpCeywnvPux5psZVpvblGDop1oPiZkdsVI+NhsA0c4BE6YT0fNVK8Oqxf5Dgt5k7g== + dependencies: + "@inquirer/input" "^1.2.13" + "@inquirer/type" "^1.1.5" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + +"@inquirer/prompts@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-3.2.0.tgz#8f4feaa81560d22e77b55c676e9296a108daf5b1" + integrity sha512-sfT7eDoveChXr8iIfwUYkoVBjUcKqXluhjM0EVhRhN59ZuJCc5DAdnuKwaFXomwESDoN0f+2zHy+MpxUg+EZuQ== + dependencies: + "@inquirer/checkbox" "^1.4.0" + "@inquirer/confirm" "^2.0.14" + "@inquirer/core" "^5.1.0" + "@inquirer/editor" "^1.2.12" + "@inquirer/expand" "^1.1.13" + "@inquirer/input" "^1.2.13" + "@inquirer/password" "^1.1.13" + "@inquirer/rawlist" "^1.2.13" + "@inquirer/select" "^1.3.0" + +"@inquirer/rawlist@^1.2.13": + version "1.2.13" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-1.2.13.tgz#e74f003d417add415fea8c349d186eef7cda5032" + integrity sha512-f+bASrCY2x2F90MrBYX7nUSetL6FsVLfskhGWEyVwj6VIXzc9T878z3v7KU3V10D1trWrCVHOdeqEcbnO68yhg== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + chalk "^4.1.2" + +"@inquirer/select@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-1.3.0.tgz#00dfa5068bea85bffeb7aa7c402407bb590c8cd4" + integrity sha512-3sL5odCDYI+i+piAFqFa5ULDUKEpc0U1zEY4Wm6gjP6nMAHWM8r1UzMlpQXCyHny91Tz+oeSLeKinAde0z6R7w== + dependencies: + "@inquirer/core" "^5.1.0" + "@inquirer/type" "^1.1.5" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/type@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.1.5.tgz#b8c171f755859c8159b10e41e1e3a88f0ca99d7f" + integrity sha512-wmwHvHozpPo4IZkkNtbYenem/0wnfI6hvOcGKmPEa0DwuaH5XUQzFqy6OpEpjEegZMhYIk8HDYITI16BPLtrRA== + "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -207,11 +326,6 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@ljharb/through@^2.3.9": - version "2.3.9" - resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.9.tgz#85f221eb82f9d555e180e87d6e50fb154af85408" - integrity sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -331,6 +445,13 @@ dependencies: "@types/node" "*" +"@types/mute-stream@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.2.tgz#5a011b17307364e48591ac6829a8e40e1c10c6b0" + integrity sha512-FpiGjk6+IOrN0lZEfUUjdra1csU1VxwYFj4S0Zj+TJpu5x5mZW30RkEZojTadrNZHNmpCHgoE62IQZAH0OeuIA== + dependencies: + "@types/node" "*" + "@types/node@*": version "20.4.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.9.tgz#c7164e0f8d3f12dfae336af0b1f7fdec8c6b204f" @@ -341,6 +462,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.4.tgz#bf8ae9875528929cc9930dc3f066cd0481fe1231" integrity sha512-ATL4WLgr7/W40+Sp1WnNTSKbgVn6Pvhc/2RHAdt8fl6NsQyp4oPCi2eKcGOvA494bwf1K/W6nGgZ9TwDqvpjdw== +"@types/node@^20.8.2": + version "20.8.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.9.tgz#646390b4fab269abce59c308fc286dcd818a2b08" + integrity sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg== + dependencies: + undici-types "~5.26.4" + "@types/prop-types@*": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" @@ -365,6 +493,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@typescript-eslint/eslint-plugin@^5.59.9": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" @@ -718,15 +851,6 @@ big-integer@^1.6.44: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - bl@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" @@ -758,14 +882,6 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -830,7 +946,7 @@ chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -838,7 +954,7 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.0.0, chalk@^5.2.0, chalk@^5.3.0: +chalk@^5.0.0, chalk@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== @@ -855,13 +971,6 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" @@ -869,11 +978,16 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" -cli-spinners@^2.5.0, cli-spinners@^2.6.1: +cli-spinners@^2.6.1: version "2.9.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== +cli-spinners@^2.9.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.1.tgz#9c0b9dad69a6d47cbb4333c14319b060ed395a35" + integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== + cli-width@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" @@ -1245,11 +1359,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== - "eslint-config-prettier@>= 8.7.0": version "9.0.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" @@ -1559,13 +1668,12 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -figures@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-5.0.0.tgz#126cd055052dea699f8a54e8c9450e6ecfc44d5f" - integrity sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg== +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: - escape-string-regexp "^5.0.0" - is-unicode-supported "^1.2.0" + escape-string-regexp "^1.0.5" file-entry-cache@^6.0.1: version "6.0.1" @@ -1868,7 +1976,7 @@ iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -1904,27 +2012,6 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inquirer@^9.2.0: - version "9.2.10" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.2.10.tgz#495a846fd6722ffadba896bd9d93e1e5a7add5c7" - integrity sha512-tVVNFIXU8qNHoULiazz612GFl+yqNfjMTbLuViNJE/d860Qxrd3NMrse8dm40VUQLOQeULvaQF8lpAhvysjeyA== - dependencies: - "@ljharb/through" "^2.3.9" - ansi-escapes "^4.3.2" - chalk "^5.3.0" - cli-cursor "^3.1.0" - cli-width "^4.1.0" - external-editor "^3.1.0" - figures "^5.0.0" - lodash "^4.17.21" - mute-stream "1.0.0" - ora "^5.4.1" - run-async "^3.0.0" - rxjs "^7.8.1" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wrap-ansi "^6.2.0" - internal-slot@^1.0.3, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" @@ -2016,11 +2103,6 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - is-interactive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" @@ -2094,12 +2176,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: dependencies: which-typed-array "^1.1.11" -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-unicode-supported@^1.1.0, is-unicode-supported@^1.2.0: +is-unicode-supported@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== @@ -2241,19 +2318,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - log-symbols@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" @@ -2368,7 +2432,7 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mute-stream@1.0.0: +mute-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== @@ -2550,21 +2614,6 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - ora@^6.3.0: version "6.3.1" resolved "https://registry.yarnpkg.com/ora/-/ora-6.3.1.tgz#a4e9e5c2cf5ee73c259e8b410273e706a2ad3ed6" @@ -2837,14 +2886,6 @@ resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - restore-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" @@ -2891,13 +2932,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.8.1: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - safe-array-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" @@ -3021,6 +3055,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3079,7 +3118,7 @@ stdin-discarder@^0.1.0: dependencies: bl "^5.0.0" -string-width@^4.1.0, string-width@^4.2.3: +string-width@^4.1.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3323,7 +3362,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.5.0, tslib@^2.6.0: +tslib@^2.5.0, tslib@^2.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== @@ -3416,6 +3455,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"