From c29c45f21138b4fd6b64ce4112e4a9543ba6f2d8 Mon Sep 17 00:00:00 2001 From: William Huang Date: Thu, 14 Sep 2023 13:26:08 +0800 Subject: [PATCH] Initialize rush plugins repository --- .gitattributes | 77 + .github/PULL_REQUEST_TEMPLATE.md | 30 + .github/workflows/main.yaml | 29 + .github/workflows/publish.yml | 29 + .gitignore | 70 + .prettierignore | 108 + .prettierrc.js | 13 + .vscode/settings.json | 25 + CONTRIBUTING.md | 76 + LICENSE | 21 + Makefile | 15 + README.md | 66 + .../rush-plugin-for-command/.eslintrc.js | 14 + .../rush-plugin-for-command/.gitignore | 1 + .../rush-plugin-for-command/.npmignore | 34 + .../rush-plugin-for-command/LICENSE | 21 + .../rush-plugin-for-command/README.md | 7 + .../rush-plugin-for-command/command-line.json | 13 + .../rush-plugin-for-command/config/heft.json | 12 + .../rush-plugin-for-command/init.config.ts | 34 + .../lint-staged.config.cjs | 5 + .../rush-plugin-for-command/package.json | 38 + .../rush-plugin-manifest.json | 10 + .../src/helpers/terminal.ts | 6 + .../rush-plugin-for-command/src/index.ts | 19 + .../rush-plugin-for-command/tsconfig.json | 97 + common/_templates/template.json | 8 + .../command-plugins/package.json | 14 + .../command-plugins/pnpm-lock.yaml | 3733 ++++++++ .../command-line.json | 29 + .../rush-plugin-manifest.json | 10 + .../rush-audit-cache-plugin/command-line.json | 40 + .../rush-plugin-manifest.json | 10 + .../command-line.json | 39 + .../rush-plugin-manifest.json | 10 + .../rush-lint-staged-plugin/command-line.json | 13 + .../rush-plugin-manifest.json | 10 + .../rush-plugin-manifest.json | 10 + .../rush-sort-package-json/command-line.json | 12 + .../rush-plugin-manifest.json | 10 + .../command-line.json | 13 + .../autoinstallers/rush-prettier/package.json | 9 + .../rush-prettier/pnpm-lock.yaml | 296 + common/config/rush/.npmrc | 22 + common/config/rush/.npmrc-publish | 23 + common/config/rush/.pnpmfile.cjs | 38 + common/config/rush/artifactory.json | 85 + common/config/rush/build-cache.json | 84 + common/config/rush/command-line.json | 344 + common/config/rush/common-versions.json | 62 + common/config/rush/experiments.json | 38 + common/config/rush/pnpm-lock.yaml | 7957 +++++++++++++++++ common/config/rush/repo-state.json | 4 + common/config/rush/rush-plugins.json | 55 + common/config/rush/version-policies.json | 102 + common/git-hooks/commit-msg.sample | 25 + common/git-hooks/pre-commit | 12 + common/scripts/install-run-rush.js | 116 + common/scripts/install-run-rushx.js | 18 + common/scripts/install-run.js | 500 ++ cspell.json | 21 + lint-staged.config.cjs | 5 + .../rush-archive-project-plugin/.eslintrc.js | 14 + .../rush-archive-project-plugin/.gitignore | 1 + .../rush-archive-project-plugin/.npmignore | 36 + .../CHANGELOG.json | 151 + .../rush-archive-project-plugin/CHANGELOG.md | 88 + .../rush-archive-project-plugin/LICENSE | 21 + .../rush-archive-project-plugin/README.md | 45 + .../command-line.json | 29 + .../config/heft.json | 14 + .../config/jest.config.json | 3 + .../fixtures/monorepo-1/demo/package.json | 4 + .../fixtures/monorepo-1/rush.json | 16 + .../common/_graveyard/demo-project.tar.gz | Bin 0 -> 345 bytes .../fixtures/monorepo-2/other/package.json | 4 + .../fixtures/monorepo-2/rush.json | 28 + .../monorepo-3/apps/my-app/package.json | 4 + .../monorepo-3/libraries/my-lib/package.json | 4 + .../fixtures/monorepo-3/rush.json | 32 + .../_graveyard/@my-company/my-app.tar.gz | Bin 0 -> 298 bytes .../monorepo-4/libraries/my-lib/package.json | 4 + .../fixtures/monorepo-4/rush.json | 28 + .../monorepo-5/apps/my-app/package.json | 7 + .../monorepo-5/libraries/my-lib/package.json | 4 + .../fixtures/monorepo-5/rush.json | 32 + .../lint-staged.config.cjs | 5 + .../rush-archive-project-plugin/package.json | 55 + .../rush-plugin-manifest.json | 10 + .../src/__mocks__/ora.js | 8 + .../rush-archive-project-plugin/src/cli.ts | 76 + .../src/commands/archive.ts | 169 + .../test/__snapshots__/archive.test.ts.snap | 6 + .../src/commands/test/archive.test.ts | 127 + .../src/commands/test/unarchive.test.ts | 94 + .../src/commands/unarchive.ts | 101 + .../src/logic/generateMD.ts | 26 + .../src/logic/git.ts | 78 + .../src/logic/graveyard.ts | 55 + .../src/logic/projectMetadata.ts | 36 + .../src/logic/promptRushUpdate.ts | 46 + .../src/logic/rushConfiguration.ts | 24 + .../rush-archive-project-plugin/tsconfig.json | 95 + .../rush-audit-cache-plugin/.eslintrc.js | 14 + .../rush-audit-cache-plugin/.gitignore | 1 + .../rush-audit-cache-plugin/.npmignore | 34 + .../rush-audit-cache-plugin/CHANGELOG.json | 221 + .../rush-audit-cache-plugin/CHANGELOG.md | 130 + rush-plugins/rush-audit-cache-plugin/LICENSE | 21 + .../rush-audit-cache-plugin/README.md | 24 + .../rush-audit-cache-plugin/command-line.json | 75 + .../rush-audit-cache-plugin/config/heft.json | 25 + .../config/jest.config.json | 3 + .../docs/media/rush-audit-cache-arch.png | Bin 0 -> 135548 bytes .../media/rush-audit-cache-demo-usage.png | Bin 0 -> 470465 bytes ...proposal-for-rush-build-diagnostic-tool.md | 44 + .../docs/rush-audit-cache-tech-note.md | 36 + .../lint-staged.config.cjs | 5 + .../rush-audit-cache-plugin/package.json | 43 + .../rush-plugin-manifest.json | 11 + .../rush-audit-cache-plugin/src/auditCache.ts | 191 + .../rush-audit-cache-plugin/src/bin.ts | 95 + .../src/core/Analyzer.ts | 216 + .../src/core/Linux/LinuxTraceExecutor.ts | 99 + .../src/core/Linux/StraceLogParser.ts | 284 + .../src/core/ReadFileResolver.ts | 101 + .../src/core/TraceExecutor.ts | 23 + .../src/core/WriteFileResolver.ts | 66 + .../src/core/base/BaseFileResolver.ts | 132 + .../src/core/base/BaseTraceExecutor.ts | 29 + .../src/core/test/ReadFileResolver.test.ts | 232 + .../src/core/test/WriteFileResolver.test.ts | 226 + .../src/helpers/constants.ts | 8 + .../src/helpers/rushProject.ts | 132 + .../src/helpers/terminal.ts | 7 + .../src/helpers/utils.ts | 12 + .../rush-audit-cache-plugin/src/index.ts | 3 + .../src/schemas/plugin-options.schema.json | 69 + .../rush-audit-cache-plugin/tsconfig.json | 97 + rush-plugins/rush-git-lfs-plugin/.eslintrc.js | 14 + rush-plugins/rush-git-lfs-plugin/.gitignore | 1 + rush-plugins/rush-git-lfs-plugin/.npmignore | 34 + .../rush-git-lfs-plugin/CHANGELOG.json | 53 + rush-plugins/rush-git-lfs-plugin/CHANGELOG.md | 32 + rush-plugins/rush-git-lfs-plugin/LICENSE | 21 + rush-plugins/rush-git-lfs-plugin/README.md | 85 + .../rush-git-lfs-plugin/command-line.json | 59 + .../rush-git-lfs-plugin/config/heft.json | 18 + .../config/jest.config.json | 3 + .../lint-staged.config.cjs | 5 + rush-plugins/rush-git-lfs-plugin/package.json | 47 + .../rush-plugin-manifest.json | 15 + .../schema/git-lfs-option.schema.json | 25 + rush-plugins/rush-git-lfs-plugin/src/bin.ts | 54 + .../rush-git-lfs-plugin/src/constant.ts | 9 + .../rush-git-lfs-plugin/src/executor/index.ts | 4 + .../src/executor/modules/base.ts | 9 + .../src/executor/modules/check.ts | 159 + .../src/executor/modules/index.ts | 1 + .../rush-git-lfs-plugin/src/executor/pull.ts | 65 + .../src/executor/run-check.ts | 53 + .../src/executor/version.ts | 8 + .../src/helpers/file-path-analyser.ts | 75 + .../src/helpers/terminal.ts | 13 + .../rush-git-lfs-plugin/src/helpers/type.ts | 6 + rush-plugins/rush-git-lfs-plugin/src/index.ts | 2 + .../rush-git-lfs-plugin/src/options.ts | 35 + rush-plugins/rush-git-lfs-plugin/src/pull.ts | 32 + .../src/tests/executor/core.test.ts | 78 + .../src/tests/executor/verison.test.ts | 15 + .../tests/helpers/file-path-analyser.test.ts | 64 + .../src/tests/setup/TestFileFactory.ts | 63 + .../rush-git-lfs-plugin/tsconfig.json | 97 + .../rush-init-project-plugin/.eslintrc.js | 15 + .../rush-init-project-plugin/.gitignore | 3 + .../rush-init-project-plugin/.npmignore | 34 + .../rush-init-project-plugin/CHANGELOG.json | 316 + .../rush-init-project-plugin/CHANGELOG.md | 181 + rush-plugins/rush-init-project-plugin/LICENSE | 21 + .../rush-init-project-plugin/README.md | 55 + .../command-line.json | 46 + .../rush-init-project-plugin/config/heft.json | 16 + .../config/jest.config.json | 3 + .../docs/init_project_configuration.md | 551 ++ .../lint-staged.config.cjs | 5 + .../rush-init-project-plugin/package.json | 66 + .../rush-plugin-manifest.json | 10 + .../src/actions/addProjectToRushJson.ts | 33 + .../src/actions/rushRushUpdate.ts | 15 + .../src/actions/sortPackageJson.ts | 19 + .../rush-init-project-plugin/src/cli.ts | 38 + .../rush-init-project-plugin/src/hooks.ts | 64 + .../rush-init-project-plugin/src/index.ts | 10 + .../src/init-project.ts | 110 + .../src/logic/GitConfig.ts | 22 + .../src/logic/TemplateConfiguration.ts | 116 + .../src/logic/loadGlobalConfiguration.ts | 74 + .../src/logic/loadRushConfiguration.ts | 23 + .../src/logic/template.schema.json | 37 + .../src/logic/templateFolder.ts | 55 + .../rush-init-project-plugin/src/plopfile.ts | 337 + .../rush-init-project-plugin/src/terminal.ts | 97 + .../addManyCustomEngine.test.ts.snap | 25 + .../addManyCustomEngine.test.ts | 55 + .../addManyCustomEngine/plop-templates/index | 20 + .../plop-templates/pkg.json | 4 + .../src/test/addManyCustomEngine/plopfile.js | 9 + .../src/test/addManyRaw/addMany.test.ts | 50 + .../test/addManyRaw/plop-templates/pkg.json | 4 + .../src/test/utils.ts | 5 + .../rush-init-project-plugin/src/ui/COLORS.ts | 234 + .../src/ui/EMIT_EVENTS.ts | 9 + .../src/ui/EventManager.ts | 49 + .../ui/components/AutoCompleteComponent.ts | 271 + .../src/ui/components/BaseFieldComponent.ts | 251 + .../components/BlessedHiddenInputComponent.ts | 21 + .../src/ui/components/CheckboxComponent.ts | 126 + .../src/ui/components/ConfirmComponent.ts | 87 + .../src/ui/components/InputComponent.ts | 108 + .../src/ui/components/ListComponent.ts | 177 + .../src/ui/components/Warning.ts | 22 + .../src/ui/components/form.ts | 248 + .../src/ui/components/steps.ts | 44 + .../src/ui/components/templateList.ts | 29 + .../rush-init-project-plugin/src/ui/index.ts | 128 + .../rush-init-project-plugin/tsconfig.json | 97 + .../rush-init-project-plugin/typings.d.ts | 5 + .../rush-lint-staged-plugin/.eslintrc.js | 14 + .../rush-lint-staged-plugin/.gitignore | 1 + .../rush-lint-staged-plugin/.npmignore | 34 + .../rush-lint-staged-plugin/CHANGELOG.json | 101 + .../rush-lint-staged-plugin/CHANGELOG.md | 60 + rush-plugins/rush-lint-staged-plugin/LICENSE | 21 + .../rush-lint-staged-plugin/README.md | 68 + .../rush-lint-staged-plugin/command-line.json | 13 + .../rush-lint-staged-plugin/config/heft.json | 12 + .../lint-staged.config.cjs | 5 + .../rush-lint-staged-plugin/package.json | 43 + .../rush-plugin-manifest.json | 10 + .../src/helpers/terminal.ts | 6 + .../rush-lint-staged-plugin/src/index.ts | 23 + .../rush-lint-staged-plugin/src/typings.d.ts | 1 + .../rush-lint-staged-plugin/tsconfig.json | 97 + .../.eslintrc.js | 14 + .../rush-print-log-if-error-plugin/.gitignore | 1 + .../CHANGELOG.json | 65 + .../CHANGELOG.md | 39 + .../rush-print-log-if-error-plugin/LICENSE | 21 + .../rush-print-log-if-error-plugin/README.md | 32 + .../command-line.json | 13 + .../config/heft.json | 12 + .../lint-staged.config.cjs | 5 + .../package.json | 39 + .../rush-plugin-manifest.json | 10 + .../src/helpers/loadRushConfiguration.ts | 23 + .../src/helpers/terminal.ts | 6 + .../src/index.ts | 77 + .../tsconfig.json | 97 + .../rush-sort-package-json/.eslintrc.js | 14 + .../rush-sort-package-json/.gitignore | 1 + .../rush-sort-package-json/CHANGELOG.json | 41 + .../rush-sort-package-json/CHANGELOG.md | 25 + rush-plugins/rush-sort-package-json/LICENSE | 21 + rush-plugins/rush-sort-package-json/README.md | 33 + .../rush-sort-package-json/command-line.json | 12 + .../rush-sort-package-json/config/heft.json | 12 + .../lint-staged.config.cjs | 5 + .../rush-sort-package-json/package.json | 40 + .../rush-plugin-manifest.json | 10 + .../src/helpers/loadRushConfiguration.ts | 23 + .../src/helpers/terminal.ts | 6 + .../rush-sort-package-json/src/index.ts | 33 + .../src/sortPackageJson.ts | 12 + .../rush-sort-package-json/tsconfig.json | 97 + .../rush-upgrade-self-plugin/.eslintrc.js | 14 + .../rush-upgrade-self-plugin/.gitignore | 1 + .../rush-upgrade-self-plugin/.npmignore | 34 + .../rush-upgrade-self-plugin/CHANGELOG.json | 154 + .../rush-upgrade-self-plugin/CHANGELOG.md | 92 + rush-plugins/rush-upgrade-self-plugin/LICENSE | 21 + .../rush-upgrade-self-plugin/README.md | 32 + .../command-line.json | 13 + .../rush-upgrade-self-plugin/config/heft.json | 12 + .../lint-staged.config.cjs | 5 + .../rush-upgrade-self-plugin/package.json | 50 + .../rush-plugin-manifest.json | 10 + .../rush-upgrade-self-plugin/src/cli.ts | 20 + .../src/upgrade-self.ts | 188 + .../rush-upgrade-self-plugin/tsconfig.json | 95 + rush.json | 501 ++ 290 files changed, 27230 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/main.yaml create mode 100644 .github/workflows/publish.yml create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 .vscode/settings.json create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 common/_templates/rush-plugin-for-command/.eslintrc.js create mode 100644 common/_templates/rush-plugin-for-command/.gitignore create mode 100644 common/_templates/rush-plugin-for-command/.npmignore create mode 100644 common/_templates/rush-plugin-for-command/LICENSE create mode 100644 common/_templates/rush-plugin-for-command/README.md create mode 100644 common/_templates/rush-plugin-for-command/command-line.json create mode 100644 common/_templates/rush-plugin-for-command/config/heft.json create mode 100644 common/_templates/rush-plugin-for-command/init.config.ts create mode 100644 common/_templates/rush-plugin-for-command/lint-staged.config.cjs create mode 100644 common/_templates/rush-plugin-for-command/package.json create mode 100644 common/_templates/rush-plugin-for-command/rush-plugin-manifest.json create mode 100644 common/_templates/rush-plugin-for-command/src/helpers/terminal.ts create mode 100644 common/_templates/rush-plugin-for-command/src/index.ts create mode 100644 common/_templates/rush-plugin-for-command/tsconfig.json create mode 100644 common/_templates/template.json create mode 100644 common/autoinstallers/command-plugins/package.json create mode 100644 common/autoinstallers/command-plugins/pnpm-lock.yaml create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-archive-project-plugin/command-line.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-audit-cache-plugin/command-line.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-init-project-plugin/command-line.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-lint-staged-plugin/command-line.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-sort-package-json/command-line.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json create mode 100644 common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-upgrade-self-plugin/command-line.json create mode 100644 common/autoinstallers/rush-prettier/package.json create mode 100644 common/autoinstallers/rush-prettier/pnpm-lock.yaml create mode 100644 common/config/rush/.npmrc create mode 100644 common/config/rush/.npmrc-publish create mode 100644 common/config/rush/.pnpmfile.cjs create mode 100644 common/config/rush/artifactory.json create mode 100644 common/config/rush/build-cache.json create mode 100644 common/config/rush/command-line.json create mode 100644 common/config/rush/common-versions.json create mode 100644 common/config/rush/experiments.json create mode 100644 common/config/rush/pnpm-lock.yaml create mode 100644 common/config/rush/repo-state.json create mode 100644 common/config/rush/rush-plugins.json create mode 100644 common/config/rush/version-policies.json create mode 100644 common/git-hooks/commit-msg.sample create mode 100644 common/git-hooks/pre-commit create mode 100644 common/scripts/install-run-rush.js create mode 100644 common/scripts/install-run-rushx.js create mode 100644 common/scripts/install-run.js create mode 100644 cspell.json create mode 100644 lint-staged.config.cjs create mode 100644 rush-plugins/rush-archive-project-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-archive-project-plugin/.gitignore create mode 100644 rush-plugins/rush-archive-project-plugin/.npmignore create mode 100644 rush-plugins/rush-archive-project-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-archive-project-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-archive-project-plugin/LICENSE create mode 100644 rush-plugins/rush-archive-project-plugin/README.md create mode 100644 rush-plugins/rush-archive-project-plugin/command-line.json create mode 100644 rush-plugins/rush-archive-project-plugin/config/heft.json create mode 100644 rush-plugins/rush-archive-project-plugin/config/jest.config.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/demo/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/rush.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-2/common/_graveyard/demo-project.tar.gz create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-2/other/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-2/rush.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-3/apps/my-app/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-3/libraries/my-lib/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-3/rush.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/common/_graveyard/@my-company/my-app.tar.gz create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/libraries/my-lib/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/rush.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/apps/my-app/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/libraries/my-lib/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/rush.json create mode 100644 rush-plugins/rush-archive-project-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-archive-project-plugin/package.json create mode 100644 rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-archive-project-plugin/src/__mocks__/ora.js create mode 100644 rush-plugins/rush-archive-project-plugin/src/cli.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/commands/archive.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/commands/test/__snapshots__/archive.test.ts.snap create mode 100644 rush-plugins/rush-archive-project-plugin/src/commands/test/archive.test.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/commands/test/unarchive.test.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/commands/unarchive.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/generateMD.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/git.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/graveyard.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/projectMetadata.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/promptRushUpdate.ts create mode 100644 rush-plugins/rush-archive-project-plugin/src/logic/rushConfiguration.ts create mode 100644 rush-plugins/rush-archive-project-plugin/tsconfig.json create mode 100644 rush-plugins/rush-audit-cache-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-audit-cache-plugin/.gitignore create mode 100644 rush-plugins/rush-audit-cache-plugin/.npmignore create mode 100644 rush-plugins/rush-audit-cache-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-audit-cache-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-audit-cache-plugin/LICENSE create mode 100644 rush-plugins/rush-audit-cache-plugin/README.md create mode 100644 rush-plugins/rush-audit-cache-plugin/command-line.json create mode 100644 rush-plugins/rush-audit-cache-plugin/config/heft.json create mode 100644 rush-plugins/rush-audit-cache-plugin/config/jest.config.json create mode 100644 rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-arch.png create mode 100644 rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-demo-usage.png create mode 100644 rush-plugins/rush-audit-cache-plugin/docs/proposal-for-rush-build-diagnostic-tool.md create mode 100644 rush-plugins/rush-audit-cache-plugin/docs/rush-audit-cache-tech-note.md create mode 100644 rush-plugins/rush-audit-cache-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-audit-cache-plugin/package.json create mode 100644 rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-audit-cache-plugin/src/auditCache.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/bin.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/Analyzer.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/Linux/LinuxTraceExecutor.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/Linux/StraceLogParser.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/ReadFileResolver.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/TraceExecutor.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/WriteFileResolver.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/base/BaseFileResolver.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/base/BaseTraceExecutor.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/test/ReadFileResolver.test.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/core/test/WriteFileResolver.test.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/helpers/constants.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/helpers/rushProject.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/helpers/terminal.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/helpers/utils.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/index.ts create mode 100644 rush-plugins/rush-audit-cache-plugin/src/schemas/plugin-options.schema.json create mode 100644 rush-plugins/rush-audit-cache-plugin/tsconfig.json create mode 100644 rush-plugins/rush-git-lfs-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-git-lfs-plugin/.gitignore create mode 100644 rush-plugins/rush-git-lfs-plugin/.npmignore create mode 100644 rush-plugins/rush-git-lfs-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-git-lfs-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-git-lfs-plugin/LICENSE create mode 100644 rush-plugins/rush-git-lfs-plugin/README.md create mode 100644 rush-plugins/rush-git-lfs-plugin/command-line.json create mode 100644 rush-plugins/rush-git-lfs-plugin/config/heft.json create mode 100644 rush-plugins/rush-git-lfs-plugin/config/jest.config.json create mode 100644 rush-plugins/rush-git-lfs-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-git-lfs-plugin/package.json create mode 100644 rush-plugins/rush-git-lfs-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-git-lfs-plugin/schema/git-lfs-option.schema.json create mode 100644 rush-plugins/rush-git-lfs-plugin/src/bin.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/constant.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/index.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/modules/base.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/modules/check.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/modules/index.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/pull.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/run-check.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/executor/version.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/helpers/file-path-analyser.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/helpers/terminal.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/helpers/type.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/index.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/options.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/pull.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/tests/executor/core.test.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/tests/executor/verison.test.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/tests/helpers/file-path-analyser.test.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/src/tests/setup/TestFileFactory.ts create mode 100644 rush-plugins/rush-git-lfs-plugin/tsconfig.json create mode 100644 rush-plugins/rush-init-project-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-init-project-plugin/.gitignore create mode 100644 rush-plugins/rush-init-project-plugin/.npmignore create mode 100644 rush-plugins/rush-init-project-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-init-project-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-init-project-plugin/LICENSE create mode 100644 rush-plugins/rush-init-project-plugin/README.md create mode 100644 rush-plugins/rush-init-project-plugin/command-line.json create mode 100644 rush-plugins/rush-init-project-plugin/config/heft.json create mode 100644 rush-plugins/rush-init-project-plugin/config/jest.config.json create mode 100644 rush-plugins/rush-init-project-plugin/docs/init_project_configuration.md create mode 100644 rush-plugins/rush-init-project-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-init-project-plugin/package.json create mode 100644 rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-init-project-plugin/src/actions/addProjectToRushJson.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/actions/rushRushUpdate.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/actions/sortPackageJson.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/cli.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/hooks.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/index.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/init-project.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/GitConfig.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/TemplateConfiguration.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/loadGlobalConfiguration.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/loadRushConfiguration.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/template.schema.json create mode 100644 rush-plugins/rush-init-project-plugin/src/logic/templateFolder.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/plopfile.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/terminal.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/__snapshots__/addManyCustomEngine.test.ts.snap create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/addManyCustomEngine.test.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/index create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/pkg.json create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plopfile.js create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyRaw/addMany.test.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/test/addManyRaw/plop-templates/pkg.json create mode 100644 rush-plugins/rush-init-project-plugin/src/test/utils.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/COLORS.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/EMIT_EVENTS.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/EventManager.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/AutoCompleteComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/BaseFieldComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/BlessedHiddenInputComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/CheckboxComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/ConfirmComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/InputComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/ListComponent.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/Warning.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/form.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/steps.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/components/templateList.ts create mode 100644 rush-plugins/rush-init-project-plugin/src/ui/index.ts create mode 100644 rush-plugins/rush-init-project-plugin/tsconfig.json create mode 100644 rush-plugins/rush-init-project-plugin/typings.d.ts create mode 100644 rush-plugins/rush-lint-staged-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-lint-staged-plugin/.gitignore create mode 100644 rush-plugins/rush-lint-staged-plugin/.npmignore create mode 100644 rush-plugins/rush-lint-staged-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-lint-staged-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-lint-staged-plugin/LICENSE create mode 100644 rush-plugins/rush-lint-staged-plugin/README.md create mode 100644 rush-plugins/rush-lint-staged-plugin/command-line.json create mode 100644 rush-plugins/rush-lint-staged-plugin/config/heft.json create mode 100644 rush-plugins/rush-lint-staged-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-lint-staged-plugin/package.json create mode 100644 rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-lint-staged-plugin/src/helpers/terminal.ts create mode 100644 rush-plugins/rush-lint-staged-plugin/src/index.ts create mode 100644 rush-plugins/rush-lint-staged-plugin/src/typings.d.ts create mode 100644 rush-plugins/rush-lint-staged-plugin/tsconfig.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-print-log-if-error-plugin/.gitignore create mode 100644 rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-print-log-if-error-plugin/LICENSE create mode 100644 rush-plugins/rush-print-log-if-error-plugin/README.md create mode 100644 rush-plugins/rush-print-log-if-error-plugin/command-line.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/config/heft.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-print-log-if-error-plugin/package.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-print-log-if-error-plugin/src/helpers/loadRushConfiguration.ts create mode 100644 rush-plugins/rush-print-log-if-error-plugin/src/helpers/terminal.ts create mode 100644 rush-plugins/rush-print-log-if-error-plugin/src/index.ts create mode 100644 rush-plugins/rush-print-log-if-error-plugin/tsconfig.json create mode 100644 rush-plugins/rush-sort-package-json/.eslintrc.js create mode 100644 rush-plugins/rush-sort-package-json/.gitignore create mode 100644 rush-plugins/rush-sort-package-json/CHANGELOG.json create mode 100644 rush-plugins/rush-sort-package-json/CHANGELOG.md create mode 100644 rush-plugins/rush-sort-package-json/LICENSE create mode 100644 rush-plugins/rush-sort-package-json/README.md create mode 100644 rush-plugins/rush-sort-package-json/command-line.json create mode 100644 rush-plugins/rush-sort-package-json/config/heft.json create mode 100644 rush-plugins/rush-sort-package-json/lint-staged.config.cjs create mode 100644 rush-plugins/rush-sort-package-json/package.json create mode 100644 rush-plugins/rush-sort-package-json/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-sort-package-json/src/helpers/loadRushConfiguration.ts create mode 100644 rush-plugins/rush-sort-package-json/src/helpers/terminal.ts create mode 100644 rush-plugins/rush-sort-package-json/src/index.ts create mode 100644 rush-plugins/rush-sort-package-json/src/sortPackageJson.ts create mode 100644 rush-plugins/rush-sort-package-json/tsconfig.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/.eslintrc.js create mode 100644 rush-plugins/rush-upgrade-self-plugin/.gitignore create mode 100644 rush-plugins/rush-upgrade-self-plugin/.npmignore create mode 100644 rush-plugins/rush-upgrade-self-plugin/CHANGELOG.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/CHANGELOG.md create mode 100644 rush-plugins/rush-upgrade-self-plugin/LICENSE create mode 100644 rush-plugins/rush-upgrade-self-plugin/README.md create mode 100644 rush-plugins/rush-upgrade-self-plugin/command-line.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/config/heft.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/lint-staged.config.cjs create mode 100644 rush-plugins/rush-upgrade-self-plugin/package.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json create mode 100644 rush-plugins/rush-upgrade-self-plugin/src/cli.ts create mode 100644 rush-plugins/rush-upgrade-self-plugin/src/upgrade-self.ts create mode 100644 rush-plugins/rush-upgrade-self-plugin/tsconfig.json create mode 100644 rush.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d70f09c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,77 @@ +# Prevent Git to auto detect text files and perform LF normalization. +* -text + +# The item with `binary` is treated as binary file. +# The item with `eol=lf` is converted to LF on checkin, back to LF on checkout. +# The item with `eol=crlf` is converted to LF on checkin, back to CRLF on checkout. + +# To get full extension list in the repo, remove the node_modules folder and run the following PowerShell cmdlet. +# PS> Get-ChildItem . -Recurse | Where-Object { -not $_.PSIsContainer } | ForEach-Object { $_.Extension.ToLower() } | Sort-Object | Get-Unique + +# If new extensions are added, please refresh the repo with the following commands. +# Reference: https://git-scm.com/docs/gitattributes +# > rm .git/index # Remove the index to force Git to +# > git reset # re-scan the working directory +# > git status # Show files that will be normalized +# > git add -u +# > git add .gitattributes +# > git commit -m "Apply end-of-line normalization based on updated .gitattributes file" + +*.aspx text eol=crlf +*.bowerrc text eol=lf +*.cmd text eol=crlf +*.command text eol=lf +*.config text eol=crlf +*.cs text eol=crlf +*.csproj text eol=crlf +*.css text eol=crlf +*.dll binary +*.editorconfig text eol=lf +*.eot binary +*.example text eol=crlf +*.exe binary +*.gif binary +*.gitattributes text eol=lf +*.gitignore text eol=lf +*.gitmodules text eol=lf +*.html text eol=crlf +*.ico binary +*.jpg binary +*.js text eol=crlf +*.json text eol=crlf +*.less text eol=crlf +*.map text eol=lf +*.md text eol=crlf +*.npmignore text eol=lf +*.png binary +*.ps1 text eol=crlf +*.rels text eol=crlf +*.resx text eol=crlf +*.scss text eol=crlf +*.sln text eol=crlf +*.svg text elf=lf +*.ts text eol=crlf +*.tsx text eol=crlf +*.ttf binary +*.woff binary +*.wsp binary +*.xml text eol=crlf + +# NPM "bin" scripts MUST have LF, or else the executable fails to run on Mac. +# This fnmatch expression only matches files in a "bin" folder and without +# a period in the filename. +/*/*/bin/+([!.]) -text +# Don't allow people to merge changes to these generated files, because the result +# may be invalid. You need to run "rush update" again. +pnpm-lock.yaml merge=text +shrinkwrap.yaml merge=binary +npm-shrinkwrap.json merge=binary +yarn.lock merge=binary + +# Rush's JSON config files use JavaScript-style code comments. The rule below prevents pedantic +# syntax highlighters such as GitHub's from highlighting these comments as errors. Your text editor +# may also require a special configuration to allow comments in JSON. +# +# For more information, see this issue: https://github.com/microsoft/rushstack/issues/1088 +# +*.json linguist-language=JSON-with-Comments diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..6749e1f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,30 @@ + + + +### Basic Checks + +Have you run `rush change` for this change? + +- [ ] Yes +- [ ] No + +If **No**, please run `rush change` before, this is necessary. + +If adding a **new feature**, the PR's description includes: + +- [ ] Reason for adding this feature +- [ ] How to use +- [ ] A basic example + +**Does this PR introduce a breaking change?** (check one) + +- [ ] Yes +- [ ] No + +If yes, please describe the impact and migration path for existing applications: + +### Summary + +### Detail + +### How to test it diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..7c38e0a --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,29 @@ +name: Build and Test +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + - name: Git config user + uses: snow-actions/git-config-user@v1.0.0 + with: + name: tiktokbot + email: tiktokbot@users.noreply.github.com + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Verify Change Logs + run: node common/scripts/install-run-rush.js change --verify + - name: Rush Install + run: node common/scripts/install-run-rush.js install + - name: Rush rebuild + run: node common/scripts/install-run-rush.js rebuild --verbose --production + - name: Rush test + run: node common/scripts/install-run-rush.js test --verbose diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..57ad81d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,29 @@ +name: Publish NPM Packages +on: + workflow_dispatch +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + token: ${{ secrets.BOT_ACCESS_TOKEN }} + - name: Git config user + uses: snow-actions/git-config-user@v1.0.0 + with: + name: tiktokbot + email: tiktokbot@users.noreply.github.com + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Rush Install + run: node common/scripts/install-run-rush.js install + - name: Rush build + run: node common/scripts/install-run-rush.js build --verbose --production + - name: Rush test + run: node common/scripts/install-run-rush.js test --verbose + - name: Rush publish + run: node common/scripts/install-run-rush.js publish --apply --publish --target-branch ${{ github.ref_name }} + env: + NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1eff296 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://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/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# OS X temporary files +.DS_Store + +# Rush temporary files +common/deploy/ +common/temp/ +common/autoinstallers/*/.npmrc +**/.rush/temp/ + +# Heft +.heft + +temp/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f577e87 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,108 @@ +#------------------------------------------------------------------------------------------------------------------- +# Keep this section in sync with .gitignore +#------------------------------------------------------------------------------------------------------------------- + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://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/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# OS X temporary files +.DS_Store + +# Rush temporary files +common/deploy/ +common/temp/ +**/.rush/temp/ + +# Common toolchain intermediate files +temp +lib +lib-amd +lib-es6 +dist +*.scss.ts +*.sass.ts + +# Visual Studio Code +.vscode + +# Remove eventually +package-deps.json + +#------------------------------------------------------------------------------------------------------------------- +# Prettier-specific overrides +#------------------------------------------------------------------------------------------------------------------- + +# Machine-egnerated files +common/reviews +common/changes +common/scripts +common/config/rush/browser-approved-packages.json +common/config/rush/nonbrowser-approved-packages.json +CHANGELOG.* +pnpm-lock.yaml +build-tests/*/etc +dist-dev +dist-prod + +# Prettier doesn't understand the /*[LINE "HYPOTHETICAL"]*/ macros in these files: +libraries/rush-lib/assets/rush-init/ + +# These are intentionally invalid files +libraries/heft-config-file/src/test/errorCases/invalidJson/config.json + +# We'll consider enabling this later; Prettier reformats code blocks, which affects end-user content +*.md diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..738cb45 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,13 @@ +// Documentation for this file: https://prettier.io/docs/en/configuration.html +module.exports = { + // We use a larger print width because Prettier's word-wrapping seems to be tuned + // for plain JavaScript without type annotations + printWidth: 110, + // Microsoft style quotes + singleQuote: true, + // Preserve existing newlines + endOfLine: 'auto', + // For ES5, trailing commas cannot be used in function parameters; it is counterintuitive + // to use them for arrays only + trailingComma: 'none' +}; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5367d58 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,25 @@ +// Place your settings in this file to overwrite default and user settings. +{ + // Controls the rendering size of tabs in characters. Accepted values: "auto", 2, 4, 6, etc. If set to "auto", the value will be guessed when a file is opened. + "editor.tabSize": 2, + // Controls after how many characters the editor will wrap to the next line. Setting this to 0 turns on viewport width wrapping + // When enabled, will trim trailing whitespace when you save a file. + "files.trimTrailingWhitespace": true, + // Controls if the editor should automatically close brackets after opening them + "editor.autoClosingBrackets": "never", + // Configure glob patterns for excluding files and folders in searches. Inherits all glob patterns from the file.exclude setting. + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/dist": true, + "**/lib": true, + "**/lib-amd": true, + "**/test/**/temp": false, + "**/temp": true, + "**/coverage": true + }, + "files.associations": { + "**/package.json": "json", + "**/*.json": "jsonc" + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1f85336 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,76 @@ +# Setting your machine + +1. Install a LTS Node.js version, such as v14.19.1 +2. Install rush globally: `npm install -g @microsoft/rush` +3. Clone the repository: `git clone git@github.com:tiktok/rush-plugins.git` + +# Building the project + +We use Rush tool for building projects in this monorepo. + +1. Use rush to install the package dependencies: + +``` +cd rush-plugins +rush install +``` + +Note: you need to configure a Github email like **mrexample@users.noreply.github.com** + +2. Build the project in the repo: + +``` +# rush build -t +rush build -t rush-archive-project-plugin +``` + +# Testing the project + +This section shows the way to test the plugin in this repo. + +Use `rush-archive-project-plugin` for example: + +1. Modify **common/autoinstallers/command-plugins/package.json** + +``` +{ + "name": "command-plugins", + "version": "1.0.0", + "private": true, + "dependencies": { + "rush-archive-project-plugin": "1.1.3", +- "rush-audit-cache-plugin": "0.0.2", ++ "rush-audit-cache-plugin": "link:../../../rush-plugins/rush-archive-project-plugin", + "rush-init-project-plugin": "0.6.0", + "rush-lint-staged-plugin": "0.1.6", + "rush-sort-package-json": "0.0.3", + "rush-upgrade-self-plugin": "1.0.6", + "typescript": "4.4.2" + } +} +``` + +2. Update the plugins + +``` +rush update-autoinstaller --name command-plugins + +rush update +``` + +3. Test your plugin + +Since `rush-archive-project-plugin` provides `rush archive-project`, you can test it now! + +Note: You can see this approach uses a `link:` protocol to install a rush plugin package by relative path. That means you can also configure another local monorepo to use this plugin as well. + +# Submitting a Pull Request + +We welcome contributions! To submit a feature: + +1. Fork the repo. +2. Create a branch and commit your changes. +3. If you modify any package.json files, run `rush update` to make sure the `pnpm-lock.yaml` file is up to date. Commit any changes made to that file. +4. Before creating your PR, run `rush change`; If prompted, enter a change log message, commit the files that get created. +5. Create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) +6. Add the project name as a prefix to your PR title. For example: "[rush-archive-project-plugin] Added a new API feature" or "[rush-init-project-plugin] Fixed a bug in the plugin". \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/Makefile b/Makefile new file mode 100644 index 0000000..9dfec6d --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +SHELL=/bin/bash + +CURRENT_BRANCH_NAME := $(shell git branch --show-current) + +publish: + @export NPM_AUTH_TOKEN=`cat ~/.npmrc | grep registry.npmjs.org | grep _authToken | awk -F= '{print $$2}'`; \ + rush publish --apply --publish --target-branch $(CURRENT_BRANCH_NAME) + +publish-all: + @export NPM_AUTH_TOKEN=`cat ~/.npmrc | grep registry.npmjs.org | grep _authToken | awk -F= '{print $$2}'`; \ + rush publish --apply --publish --target-branch $(CURRENT_BRANCH_NAME) --include-all + +publish-dev: + @export NPM_AUTH_TOKEN=`cat ~/.npmrc | grep registry.npmjs.org | grep _authToken | awk -F= '{print $$2}'`; \ + rush publish --publish --include-all --tag dev diff --git a/README.md b/README.md new file mode 100644 index 0000000..bfe97f8 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +This repo hosts a collection of third-party plugins for [RushJS](https://rushjs.io). + +# rush-init-project-plugin + +[![npm](https://img.shields.io/npm/dt/rush-init-project-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-init-project-plugin) + +When you want to create a new project in your monorepo. There are highly chances you need copy and paste from a project already inside your monorepo. Why not reuse them, like create a project template and used in your monorepo. Yes, `rush-init-project-plugin` is for you! + +[More](./rush-plugins/rush-init-project-plugin/README.md) + +# rush-upgrade-self-plugin + +[![npm](https://img.shields.io/npm/dt/rush-upgrade-self-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-upgrade-self-plugin) + +When you maintain a Rush.js managed monorepo, and you write some toolkit based on rush related module, such as `microsoft/rush-lib`, `@rushstack/node-core-library`. Things become trivial if you want to upgrade Rush.js to latest version. You need keep the versions of those dependencies in consistency. `rush-upgrade-self-plugin` comes into rescue, it aims to help you upgrade/downgrade Rush.js version in one line. + +[More](./rush-plugins/rush-upgrade-self-plugin/README.md) + +# rush-archive-project-plugin + +[![npm](https://img.shields.io/npm/dt/rush-archive-project-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-archive-project-plugin) + +After you have tons of project in monorepo, install time gets slower, manage dependencies becomes harder, while some projects are eventually inactive. You just want a way to archive projects properly, and maybe retrieve one day :) +Now, it's time to give this plugin a try! + +[More](./rush-plugins/rush-archive-project-plugin/README.md) + +# rush-print-log-if-error-plugin + +[![npm](https://img.shields.io/npm/dt/rush-print-log-if-error-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-print-log-if-error-plugin) + +Sometimes build errors are collapsed in a remote machine, use this plugin to print the entire log if error occurs. + +[More](./rush-plugins/rush-print-log-if-error-plugin/README.md) + +# rush-sort-package-json + +[![npm](https://img.shields.io/npm/dt/rush-sort-package-json.svg?style=flat-square)](https://www.npmjs.com/package/rush-sort-package-json) + +This plugin leverages the great work of [sort-package-json](https://www.npmjs.com/package/sort-package-json) to sort `package.json` in your monorepo, and keep it consistent. + +[More](./rush-plugins/rush-sort-package-json/README.md) + +# rush-lint-staged-plugin + +[![npm](https://img.shields.io/npm/dt/rush-lint-staged-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-lint-staged-plugin) + +Are you finding alternative to `husky` in your monorepo? Rush takes care of Git hooks natively by sync hook scripts under `common/git-hooks/` folder into `.git/hooks`. So, all you need is `lint-staged`. Use this plugin to setup `lint-staged` in your monorepo! + +[More](./rush-plugins/rush-lint-staged-plugin/README.md) + +# rush-audit-cache-plugin + +[![npm](https://img.shields.io/npm/dt/rush-audit-cache-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-audit-cache-plugin) + +Use of rush build cache is a great way to speed up your build. But, how to know if the configuration for cache is working as expected? This plugin is for you! + +[More](./rush-plugins/rush-audit-cache-plugin/README.md) + +# rush-git-lfs-plugin + +[![npm](https://img.shields.io/npm/dt/rush-git-lfs-plugin.svg?style=flat-square)](https://www.npmjs.com/package/rush-git-lfs-plugin) + +Git LFS was commonly used to managed large files/binary files in your git repository. This plugin can help you to check if newly added files are correctly managed by Git LFS and prevent users from wrongly commit their local large files. + +[More](./rush-plugins/rush-git-lfs-plugin/README.md) \ No newline at end of file diff --git a/common/_templates/rush-plugin-for-command/.eslintrc.js b/common/_templates/rush-plugin-for-command/.eslintrc.js new file mode 100644 index 0000000..925d67c --- /dev/null +++ b/common/_templates/rush-plugin-for-command/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/common/_templates/rush-plugin-for-command/.gitignore b/common/_templates/rush-plugin-for-command/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/common/_templates/rush-plugin-for-command/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/common/_templates/rush-plugin-for-command/.npmignore b/common/_templates/rush-plugin-for-command/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/common/_templates/rush-plugin-for-command/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/common/_templates/rush-plugin-for-command/LICENSE b/common/_templates/rush-plugin-for-command/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/common/_templates/rush-plugin-for-command/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/common/_templates/rush-plugin-for-command/README.md b/common/_templates/rush-plugin-for-command/README.md new file mode 100644 index 0000000..ede46ed --- /dev/null +++ b/common/_templates/rush-plugin-for-command/README.md @@ -0,0 +1,7 @@ +# {{ packageName }} + +{{ description }} + +# Prerequisite + +Rush.js >= 5.57.0 diff --git a/common/_templates/rush-plugin-for-command/command-line.json b/common/_templates/rush-plugin-for-command/command-line.json new file mode 100644 index 0000000..4769e5d --- /dev/null +++ b/common/_templates/rush-plugin-for-command/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "{{ commandName }}", + "commandKind": "global", + "summary": "{{ description }}", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/common/_templates/rush-plugin-for-command/config/heft.json b/common/_templates/rush-plugin-for-command/config/heft.json new file mode 100644 index 0000000..a602554 --- /dev/null +++ b/common/_templates/rush-plugin-for-command/config/heft.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ] +} diff --git a/common/_templates/rush-plugin-for-command/init.config.ts b/common/_templates/rush-plugin-for-command/init.config.ts new file mode 100644 index 0000000..cbcb4ac --- /dev/null +++ b/common/_templates/rush-plugin-for-command/init.config.ts @@ -0,0 +1,34 @@ +import type { + IConfig, + IHooks, + IAnswers, + PromptQuestion +} from '../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin'; + +const config: IConfig = { + prompts: [], + plugins: [ + { + apply: (hooks: IHooks) => { + hooks.promptQuestion + .for('projectFolder') + .tap('command-plugin', (promptQuestion: PromptQuestion, answersSoFar: IAnswers) => { + const { unscopedPackageName } = answersSoFar; + promptQuestion.default = `rush-plugins/${unscopedPackageName}`; + return undefined; + }); + // hooks.done.tapPromise("command-plugin", async (result, answers) => { + // await new Promise((resolve) => { + // setTimeout(() => { + // console.log(result, answers); + // }, 1000); + // resolve(); + // }); + // }); + } + } + ], + defaultProjectConfiguration: {} +}; + +export default config; diff --git a/common/_templates/rush-plugin-for-command/lint-staged.config.cjs b/common/_templates/rush-plugin-for-command/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/common/_templates/rush-plugin-for-command/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/common/_templates/rush-plugin-for-command/package.json b/common/_templates/rush-plugin-for-command/package.json new file mode 100644 index 0000000..957c835 --- /dev/null +++ b/common/_templates/rush-plugin-for-command/package.json @@ -0,0 +1,38 @@ +{ + "name": "{{ packageName }}", + "version": "0.0.0", + "description": "{{ description }}", + "keywords": [ + "rush", + "plugin", + "command" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "{{ projectFolder }}" + }, + "license": "MIT", + "author": "{{ authorName }}", + "main": "lib/index.js", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/common/_templates/rush-plugin-for-command/rush-plugin-manifest.json b/common/_templates/rush-plugin-for-command/rush-plugin-manifest.json new file mode 100644 index 0000000..4050dff --- /dev/null +++ b/common/_templates/rush-plugin-for-command/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "{{ unscopedPackageName }}", + "description": "{{ description }}", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/_templates/rush-plugin-for-command/src/helpers/terminal.ts b/common/_templates/rush-plugin-for-command/src/helpers/terminal.ts new file mode 100644 index 0000000..d9b548f --- /dev/null +++ b/common/_templates/rush-plugin-for-command/src/helpers/terminal.ts @@ -0,0 +1,6 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; + +export const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); diff --git a/common/_templates/rush-plugin-for-command/src/index.ts b/common/_templates/rush-plugin-for-command/src/index.ts new file mode 100644 index 0000000..2c0c7d0 --- /dev/null +++ b/common/_templates/rush-plugin-for-command/src/index.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import { terminal } from "./helpers/terminal"; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/common/_templates/rush-plugin-for-command/tsconfig.json b/common/_templates/rush-plugin-for-command/tsconfig.json new file mode 100644 index 0000000..82917d2 --- /dev/null +++ b/common/_templates/rush-plugin-for-command/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/common/_templates/template.json b/common/_templates/template.json new file mode 100644 index 0000000..df38aad --- /dev/null +++ b/common/_templates/template.json @@ -0,0 +1,8 @@ +{ + "templates": [ + { + "displayName": "command", + "templateFolder": "rush-plugin-for-command" + } + ] +} diff --git a/common/autoinstallers/command-plugins/package.json b/common/autoinstallers/command-plugins/package.json new file mode 100644 index 0000000..43f204c --- /dev/null +++ b/common/autoinstallers/command-plugins/package.json @@ -0,0 +1,14 @@ +{ + "name": "command-plugins", + "version": "1.0.0", + "private": true, + "dependencies": { + "rush-archive-project-plugin": "1.1.3", + "rush-audit-cache-plugin": "0.0.2", + "rush-init-project-plugin": "0.6.0", + "rush-lint-staged-plugin": "0.1.6", + "rush-sort-package-json": "0.0.3", + "rush-upgrade-self-plugin": "1.0.6", + "typescript": "4.4.2" + } +} diff --git a/common/autoinstallers/command-plugins/pnpm-lock.yaml b/common/autoinstallers/command-plugins/pnpm-lock.yaml new file mode 100644 index 0000000..2ff6a01 --- /dev/null +++ b/common/autoinstallers/command-plugins/pnpm-lock.yaml @@ -0,0 +1,3733 @@ +lockfileVersion: 5.3 + +specifiers: + rush-archive-project-plugin: 1.1.3 + rush-audit-cache-plugin: 0.0.2 + rush-init-project-plugin: 0.6.0 + rush-lint-staged-plugin: 0.1.6 + rush-sort-package-json: 0.0.3 + rush-upgrade-self-plugin: 1.0.6 + typescript: 4.4.2 + +dependencies: + rush-archive-project-plugin: 1.1.3 + rush-audit-cache-plugin: 0.0.2 + rush-init-project-plugin: 0.6.0_typescript@4.4.2 + rush-lint-staged-plugin: 0.1.6 + rush-sort-package-json: 0.0.3 + rush-upgrade-self-plugin: 1.0.6 + typescript: 4.4.2 + +packages: + + /@babel/runtime-corejs3/7.20.7: + resolution: {integrity: sha512-jr9lCZ4RbRQmCR28Q8U8Fu49zvFqLxTY9AMOUz+iyMohMoAgpEcVxY+wJNay99oXOpOcCTODkk70NDN2aaJEeg==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.27.1 + regenerator-runtime: 0.13.11 + dev: false + + /@cspotcode/source-map-consumer/0.8.0: + resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==} + engines: {node: '>= 12'} + dev: false + + /@cspotcode/source-map-support/0.7.0: + resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==} + engines: {node: '>=12'} + dependencies: + '@cspotcode/source-map-consumer': 0.8.0 + dev: false + + /@gar/promisify/1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: false + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: false + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: false + + /@npmcli/fs/1.1.1: + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.3.8 + dev: false + + /@npmcli/fs/2.1.2: + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.3.8 + dev: false + + /@npmcli/git/2.1.0: + resolution: {integrity: sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==} + dependencies: + '@npmcli/promise-spawn': 1.3.2 + lru-cache: 6.0.0 + mkdirp: 1.0.4 + npm-pick-manifest: 6.1.1 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.3.8 + which: 2.0.2 + dev: false + + /@npmcli/installed-package-contents/1.0.7: + resolution: {integrity: sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==} + engines: {node: '>= 10'} + hasBin: true + dependencies: + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 + dev: false + + /@npmcli/move-file/1.1.2: + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: false + + /@npmcli/move-file/2.0.1: + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: false + + /@npmcli/node-gyp/1.0.3: + resolution: {integrity: sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==} + dev: false + + /@npmcli/promise-spawn/1.3.2: + resolution: {integrity: sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==} + dependencies: + infer-owner: 1.0.4 + dev: false + + /@npmcli/run-script/2.0.0: + resolution: {integrity: sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==} + dependencies: + '@npmcli/node-gyp': 1.0.3 + '@npmcli/promise-spawn': 1.3.2 + node-gyp: 8.4.1 + read-package-json-fast: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@rushstack/node-core-library/3.44.1: + resolution: {integrity: sha512-qK2BKuRoy6Vh83qjXxilafsUJ1soXzEX0rtkxmAC+GsKOdEVav74Df5859bvY2Ap0JNnYfGfXukX/8o3vqODyw==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.8 + timsort: 0.3.0 + z-schema: 3.18.4 + dev: false + + /@rushstack/node-core-library/3.45.0: + resolution: {integrity: sha512-YMuIJl19vQT1+g/OU9mLY6T5ZBT9uDlmeXExDQACpGuxTJW+LHNbk/lRX+eCApQI2eLBlaL4U68r3kZlqwbdmw==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.8 + timsort: 0.3.0 + z-schema: 5.0.5 + dev: false + + /@rushstack/rush-sdk/5.62.4: + resolution: {integrity: sha512-4dBir//6Vk260DMYNg8g/F8SDa/O5KkoQBGAnz3rleyD8mWt448cRaQvyGSScvXngLkDtsxFMb1bIBpIjOx0Ww==} + dependencies: + '@rushstack/node-core-library': 3.45.0 + '@types/node-fetch': 1.6.9 + tapable: 2.2.1 + dev: false + + /@tootallnate/once/1.1.2: + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + dev: false + + /@tootallnate/once/2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: false + + /@tsconfig/node10/1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: false + + /@tsconfig/node12/1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: false + + /@tsconfig/node14/1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: false + + /@tsconfig/node16/1.0.3: + resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + dev: false + + /@types/glob/7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 18.11.18 + dev: false + + /@types/inquirer/6.5.0: + resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} + dependencies: + '@types/through': 0.0.30 + rxjs: 6.6.7 + dev: false + + /@types/minimatch/5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: false + + /@types/node-fetch/1.6.9: + resolution: {integrity: sha512-n2r6WLoY7+uuPT7pnEtKJCmPUGyJ+cbyBR8Avnu4+m1nzz7DwBVuyIvvlBzCZ/nrpC7rIgb3D6pNavL7rFEa9g==} + dependencies: + '@types/node': 18.11.18 + dev: false + + /@types/node/12.20.24: + resolution: {integrity: sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==} + dev: false + + /@types/node/18.11.18: + resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + dev: false + + /@types/through/0.0.30: + resolution: {integrity: sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==} + dependencies: + '@types/node': 18.11.18 + dev: false + + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: false + + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /agentkeepalive/4.2.1: + resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 4.3.4 + depd: 1.1.2 + humanize-ms: 1.2.1 + transitivePeerDependencies: + - supports-color + dev: false + + /aggregate-error/3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: false + + /ansi-bgblack/0.1.1: + resolution: {integrity: sha512-tp8M/NCmSr6/skdteeo9UgJ2G1rG88X3ZVNZWXUxFw4Wh0PAGaAAWQS61sfBt/1QNcwMTY3EBKOMPujwioJLaw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgblue/0.1.1: + resolution: {integrity: sha512-R8JmX2Xv3+ichUQE99oL+LvjsyK+CDWo/BtVb4QUz3hOfmf2bdEmiDot3fQcpn2WAHW3toSRdjSLm6bgtWRDlA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgcyan/0.1.1: + resolution: {integrity: sha512-6SByK9q2H978bmqzuzA5NPT1lRDXl3ODLz/DjC4URO5f/HqK7dnRKfoO/xQLx/makOz7zWIbRf6+Uf7bmaPSkQ==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bggreen/0.1.1: + resolution: {integrity: sha512-8TRtOKmIPOuxjpklrkhUbqD2NnVb4WZQuIjXrT+TGKFKzl7NrL7wuNvEap3leMt2kQaCngIN1ZzazSbJNzF+Aw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgmagenta/0.1.1: + resolution: {integrity: sha512-UZYhobiGAlV4NiwOlKAKbkCyxOl1PPZNvdIdl/Ce5by45vwiyNdBetwHk/AjIpo1Ji9z+eE29PUBAjjfVmz5SA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgred/0.1.1: + resolution: {integrity: sha512-BpPHMnYmRBhcjY5knRWKjQmPDPvYU7wrgBSW34xj7JCH9+a/SEIV7+oSYVOgMFopRIadOz9Qm4zIy+mEBvUOPA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgwhite/0.1.1: + resolution: {integrity: sha512-KIF19t+HOYOorUnHTOhZpeZ3bJsjzStBG2hSGM0WZ8YQQe4c7lj9CtwnucscJDPrNwfdz6GBF+pFkVfvHBq6uw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgyellow/0.1.1: + resolution: {integrity: sha512-WyRoOFSIvOeM7e7YdlSjfAV82Z6K1+VUVbygIQ7C/VGzWYuO/d30F0PG7oXeo4uSvSywR0ozixDQvtXJEorq4Q==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-black/0.1.1: + resolution: {integrity: sha512-hl7re02lWus7lFOUG6zexhoF5gssAfG5whyr/fOWK9hxNjUFLTjhbU/b4UHWOh2dbJu9/STSUv+80uWYzYkbTQ==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-blue/0.1.1: + resolution: {integrity: sha512-8Um59dYNDdQyoczlf49RgWLzYgC2H/28W3JAIyOAU/+WkMcfZmaznm+0i1ikrE0jME6Ypk9CJ9CY2+vxbPs7Fg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bold/0.1.1: + resolution: {integrity: sha512-wWKwcViX1E28U6FohtWOP4sHFyArELHJ2p7+3BzbibqJiuISeskq6t7JnrLisUngMF5zMhgmXVw8Equjzz9OlA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-colors/0.2.0: + resolution: {integrity: sha512-ScRNUT0TovnYw6+Xo3iKh6G+VXDw2Ds7ZRnMIuKBgHY02DgvT2T2K22/tc/916Fi0W/5Z1RzDaHQwnp75hqdbA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-bgblack: 0.1.1 + ansi-bgblue: 0.1.1 + ansi-bgcyan: 0.1.1 + ansi-bggreen: 0.1.1 + ansi-bgmagenta: 0.1.1 + ansi-bgred: 0.1.1 + ansi-bgwhite: 0.1.1 + ansi-bgyellow: 0.1.1 + ansi-black: 0.1.1 + ansi-blue: 0.1.1 + ansi-bold: 0.1.1 + ansi-cyan: 0.1.1 + ansi-dim: 0.1.1 + ansi-gray: 0.1.1 + ansi-green: 0.1.1 + ansi-grey: 0.1.1 + ansi-hidden: 0.1.1 + ansi-inverse: 0.1.1 + ansi-italic: 0.1.1 + ansi-magenta: 0.1.1 + ansi-red: 0.1.1 + ansi-reset: 0.1.1 + ansi-strikethrough: 0.1.1 + ansi-underline: 0.1.1 + ansi-white: 0.1.1 + ansi-yellow: 0.1.1 + lazy-cache: 2.0.2 + dev: false + + /ansi-cyan/0.1.1: + resolution: {integrity: sha512-eCjan3AVo/SxZ0/MyIYRtkpxIu/H3xZN7URr1vXVrISxeyz8fUFz0FJziamK4sS8I+t35y4rHg1b2PklyBe/7A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-dim/0.1.1: + resolution: {integrity: sha512-zAfb1fokXsq4BoZBkL0eK+6MfFctbzX3R4UMcoWrL1n2WHewFKentTvOZv2P11u6P4NtW/V47hVjaN7fJiefOg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: false + + /ansi-gray/0.1.1: + resolution: {integrity: sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-green/0.1.1: + resolution: {integrity: sha512-WJ70OI4jCaMy52vGa/ypFSKFb/TrYNPaQ2xco5nUwE0C5H8piume/uAZNNdXXiMQ6DbRmiE7l8oNBHu05ZKkrw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-grey/0.1.1: + resolution: {integrity: sha512-+J1nM4lC+whSvf3T4jsp1KR+C63lypb+VkkwtLQMc1Dlt+nOvdZpFT0wwFTYoSlSwCcLUAaOpHF6kPkYpSa24A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-hidden/0.1.1: + resolution: {integrity: sha512-8gB1bo9ym9qZ/Obvrse1flRsfp2RE+40B23DhQcKxY+GSeaOJblLnzBOxzvmLTWbi5jNON3as7wd9rC0fNK73Q==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-inverse/0.1.1: + resolution: {integrity: sha512-Kq8Z0dBRhQhDMN/Rso1Nu9niwiTsRkJncfJZXiyj7ApbfJrGrrubHXqXI37feJZkYcIx6SlTBdNCeK0OQ6X6ag==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-italic/0.1.1: + resolution: {integrity: sha512-jreCxifSAqbaBvcibeQxcwhQDbEj7gF69XnpA6x83qbECEBaRBD1epqskrmov1z4B+zzQuEdwbWxgzvhKa+PkA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-magenta/0.1.1: + resolution: {integrity: sha512-A1Giu+HRwyWuiXKyXPw2AhG1yWZjNHWO+5mpt+P+VWYkmGRpLPry0O5gmlJQEvpjNpl4RjFV7DJQ4iozWOmkbQ==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-red/0.1.1: + resolution: {integrity: sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-reset/0.1.1: + resolution: {integrity: sha512-n+D0qD3B+h/lP0dSwXX1SZMoXufdUVotLMwUuvXa50LtBAh3f+WV8b5nFMfLL/hgoPBUt+rG/pqqzF8krlZKcw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-strikethrough/0.1.1: + resolution: {integrity: sha512-gWkLPDvHH2pC9YEKqp8dIl0mg3sRglMPvioqGDIOXiwxjxUwIJ1gF86E2o4R5yLNh8IAkwHbaMtASkJfkQ2hIA==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /ansi-underline/0.1.1: + resolution: {integrity: sha512-D+Bzwio/0/a0Fu5vJzrIT6bFk43TW46vXfSvzysOTEHcXOAUJTVMHWDbELIzGU4AVxVw2rCTb7YyWS4my2cSKQ==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-white/0.1.1: + resolution: {integrity: sha512-DJHaF2SRzBb9wZBgqIJNjjTa7JUJTO98sHeTS1sDopyKKRopL1KpaJ20R6W2f/ZGras8bYyIZDtNwYOVXNgNFg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-wrap/0.1.0: + resolution: {integrity: sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==} + engines: {node: '>=0.10.0'} + dev: false + + /ansi-yellow/0.1.1: + resolution: {integrity: sha512-6E3D4BQLXHLl3c/NwirWVZ+BCkMq2qsYxdeAGGOijKrx09FaqU+HktFL6QwAwNvgJiMLnv6AQ2C1gFZx0h1CBg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /aproba/2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /are-we-there-yet/3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + dev: false + + /arg/4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: false + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /arr-diff/4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + dev: false + + /arr-flatten/1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: false + + /arr-union/3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + dev: false + + /array-sort/0.1.4: + resolution: {integrity: sha512-BNcM+RXxndPxiZ2rd76k6nyQLRZr2/B/sdi8pQ+Joafr5AH279L40dfokSUTp8O+AaqYjXWhblBWa2st2nc4fQ==} + engines: {node: '>=0.10.0'} + dependencies: + default-compare: 1.0.0 + get-value: 2.0.6 + kind-of: 5.1.0 + dev: false + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: false + + /array-unique/0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + dev: false + + /assign-symbols/1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + dev: false + + /astral-regex/2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: false + + /atob/2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: false + + /autolinker/0.28.1: + resolution: {integrity: sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==} + dependencies: + gulp-header: 1.8.12 + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: false + + /base/0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.0 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + dev: false + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: false + + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces/2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + dev: false + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: false + + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /builtins/1.0.3: + resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} + dev: false + + /cacache/15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + dependencies: + '@npmcli/fs': 1.1.1 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.3 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.1.13 + unique-filename: 1.1.1 + dev: false + + /cacache/16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.14.1 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.1.13 + unique-filename: 2.0.1 + dev: false + + /cache-base/1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.0 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + dev: false + + /camel-case/3.0.0: + resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /change-case/3.1.0: + resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} + dependencies: + camel-case: 3.0.0 + constant-case: 2.0.0 + dot-case: 2.1.1 + header-case: 1.0.1 + is-lower-case: 1.1.3 + is-upper-case: 1.1.2 + lower-case: 1.1.4 + lower-case-first: 1.0.2 + no-case: 2.3.2 + param-case: 2.1.1 + pascal-case: 2.0.1 + path-case: 2.1.1 + sentence-case: 2.1.1 + snake-case: 2.1.0 + swap-case: 1.1.2 + title-case: 2.1.1 + upper-case: 1.1.3 + upper-case-first: 1.1.2 + dev: false + + /chardet/0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: false + + /chownr/2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + + /class-utils/0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + dev: false + + /clean-stack/2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: false + + /cli-cursor/3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: false + + /cli-spinners/2.7.0: + resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} + engines: {node: '>=6'} + dev: false + + /cli-truncate/2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: false + + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + dev: false + + /cli-width/3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: false + + /cliui/7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /clone/1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: false + + /collection-visit/1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + dev: false + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /color-support/1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + + /colorette/2.0.19: + resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} + dev: false + + /colors/1.2.5: + resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} + engines: {node: '>=0.1.90'} + dev: false + + /commander/2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + requiresBuild: true + dev: false + optional: true + + /commander/8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /commander/9.4.1: + resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} + engines: {node: ^12.20.0 || >=14} + dev: false + + /component-emitter/1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + dev: false + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: false + + /concat-with-sourcemaps/1.1.0: + resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + dependencies: + source-map: 0.6.1 + dev: false + + /console-control-strings/1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: false + + /constant-case/2.0.0: + resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} + dependencies: + snake-case: 2.1.0 + upper-case: 1.1.3 + dev: false + + /copy-descriptor/0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + dev: false + + /core-js-pure/3.27.1: + resolution: {integrity: sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==} + requiresBuild: true + dev: false + + /core-util-is/1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + + /create-frame/1.0.0: + resolution: {integrity: sha512-SnJYqAwa5Jon3cP8e3LMFBoRG2m/hX20vtOnC3ynhyAa6jmy+BqrPoicBtmKUutnJuphXPj7C54yOXF58Tl71Q==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + extend-shallow: 2.0.1 + isobject: 3.0.1 + lazy-cache: 2.0.2 + dev: false + + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: false + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: false + + /date.js/0.3.3: + resolution: {integrity: sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==} + dependencies: + debug: 3.1.0 + dev: false + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + dependencies: + ms: 2.0.0 + dev: false + + /debug/3.1.0: + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + dependencies: + ms: 2.0.0 + dev: false + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /debug/4.3.4_supports-color@9.3.1: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 9.3.1 + dev: false + + /decode-uri-component/0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: false + + /default-compare/1.0.0: + resolution: {integrity: sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 5.1.0 + dev: false + + /defaults/1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: false + + /define-property/0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.6 + dev: false + + /define-property/1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + dev: false + + /define-property/2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + isobject: 3.0.1 + dev: false + + /del/5.1.0: + resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} + engines: {node: '>=8'} + dependencies: + globby: 10.0.2 + graceful-fs: 4.2.10 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 3.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + dev: false + + /delegates/1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: false + + /depd/1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: false + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: false + + /detect-newline/3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: false + + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: false + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: false + + /dot-case/2.1.1: + resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} + dependencies: + no-case: 2.3.2 + dev: false + + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /encoding/0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true + dependencies: + iconv-lite: 0.6.3 + dev: false + optional: true + + /ent/2.2.0: + resolution: {integrity: sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==} + dev: false + + /env-paths/2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: false + + /err-code/2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + dev: false + + /error-symbol/0.1.0: + resolution: {integrity: sha512-VyjaKxUmeDX/m2lxm/aknsJ1GWDWUO2Ze2Ad8S1Pb9dykAm9TjSKp5CjrNyltYqZ5W/PO6TInAmO2/BfwMyT1g==} + engines: {node: '>=0.10.0'} + dev: false + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: false + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: false + + /expand-brackets/2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + dev: false + + /extend-shallow/2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + + /extend-shallow/3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + dev: false + + /external-editor/3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + + /extglob/2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + dev: false + + /falsey/0.3.2: + resolution: {integrity: sha512-lxEuefF5MBIVDmE6XeqCdM4BWk1+vYmGZtkbKZ/VFcg6uBBw6fXNEbWmxCjDdQlFc9hy450nkiWwM3VAW6G1qg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 5.1.0 + dev: false + + /fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + + /fastq/1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: false + + /figures/3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: false + + /fill-range/4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + dev: false + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: false + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: false + + /for-in/1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: false + + /for-own/1.0.0: + resolution: {integrity: sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + dev: false + + /fragment-cache/0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + dev: false + + /fs-exists-sync/0.1.0: + resolution: {integrity: sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==} + engines: {node: '>=0.10.0'} + dev: false + + /fs-extra/7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.10 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: false + + /fs-minipass/2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /gauge/4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + + /get-object/0.2.0: + resolution: {integrity: sha512-7P6y6k6EzEFmO/XyUyFlXm1YLJy9xeA1x/grNV8276abX5GuwUtYgKFkRFkLixw4hf4Pz9q2vgv/8Ar42R0HuQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 2.1.0 + isobject: 0.2.0 + dev: false + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + + /get-value/2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + dev: false + + /git-hooks-list/1.0.3: + resolution: {integrity: sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==} + dev: false + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: false + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /glob/8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: false + + /globby/10.0.0: + resolution: {integrity: sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==} + engines: {node: '>=8'} + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + glob: 7.2.3 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /globby/10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + glob: 7.2.3 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: false + + /gulp-header/1.8.12: + resolution: {integrity: sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==} + deprecated: Removed event-stream from gulp-header + dependencies: + concat-with-sourcemaps: 1.1.0 + lodash.template: 4.5.0 + through2: 2.0.5 + dev: false + + /handlebars-helper-create-frame/0.1.0: + resolution: {integrity: sha512-yR99Rh8JYcWSsARw/unaOUUICqG0M+SV3U4vBl3Psn78r0qXjU+cT9+IGXglNuuI3RfahvFDyEQ0l1KWthavRQ==} + engines: {node: '>=4'} + dependencies: + create-frame: 1.0.0 + isobject: 3.0.1 + dev: false + + /handlebars-helpers/0.10.0: + resolution: {integrity: sha512-QiyhQz58u/DbuV41VnfpE0nhy6YCH4vB514ajysV8SoKmP+DxU+pR+fahVyNECHj+jiwEN2VrvxD/34/yHaLUg==} + engines: {node: '>=0.12.0'} + dependencies: + arr-flatten: 1.1.0 + array-sort: 0.1.4 + create-frame: 1.0.0 + define-property: 1.0.0 + falsey: 0.3.2 + for-in: 1.0.2 + for-own: 1.0.0 + get-object: 0.2.0 + get-value: 2.0.6 + handlebars: 4.7.7 + handlebars-helper-create-frame: 0.1.0 + handlebars-utils: 1.0.6 + has-value: 1.0.0 + helper-date: 1.0.1 + helper-markdown: 1.0.0 + helper-md: 0.2.2 + html-tag: 2.0.0 + is-even: 1.0.0 + is-glob: 4.0.3 + is-number: 4.0.0 + kind-of: 6.0.3 + lazy-cache: 2.0.2 + logging-helpers: 1.0.0 + micromatch: 3.1.10 + relative: 3.0.2 + striptags: 3.2.0 + to-gfm-code-block: 0.1.1 + year: 0.2.1 + dev: false + + /handlebars-utils/1.0.6: + resolution: {integrity: sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + typeof-article: 0.1.1 + dev: false + + /handlebars/4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.7 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: false + + /has-unicode/2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: false + + /has-value/0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + dev: false + + /has-value/1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + dev: false + + /has-values/0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + dev: false + + /has-values/1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: false + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /header-case/1.0.1: + resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /helper-date/1.0.1: + resolution: {integrity: sha512-wU3VOwwTJvGr/w5rZr3cprPHO+hIhlblTJHD6aFBrKLuNbf4lAmkawd2iK3c6NbJEvY7HAmDpqjOFSI5/+Ey2w==} + engines: {node: '>=4.0'} + dependencies: + date.js: 0.3.3 + handlebars-utils: 1.0.6 + moment: 2.29.4 + dev: false + + /helper-markdown/1.0.0: + resolution: {integrity: sha512-AnDqMS4ejkQK0MXze7pA9TM3pu01ZY+XXsES6gEE0RmCGk5/NIfvTn0NmItfyDOjRAzyo9z6X7YHbHX4PzIvOA==} + engines: {node: '>=0.10.0'} + dependencies: + handlebars-utils: 1.0.6 + highlight.js: 9.18.5 + remarkable: 1.7.4 + dev: false + + /helper-md/0.2.2: + resolution: {integrity: sha512-49TaQzK+Ic7ZVTq4i1UZxRUJEmAilTk8hz7q4I0WNUaTclLR8ArJV5B3A1fe1xF2HtsDTr2gYKLaVTof/Lt84Q==} + engines: {node: '>=0.10.0'} + dependencies: + ent: 2.2.0 + extend-shallow: 2.0.1 + fs-exists-sync: 0.1.0 + remarkable: 1.7.4 + dev: false + + /highlight.js/9.18.5: + resolution: {integrity: sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA==} + deprecated: Support has ended for 9.x series. Upgrade to @latest + requiresBuild: true + dev: false + + /hosted-git-info/4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: false + + /html-tag/2.0.0: + resolution: {integrity: sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g==} + engines: {node: '>=0.10.0'} + dependencies: + is-self-closing: 1.0.1 + kind-of: 6.0.3 + dev: false + + /http-cache-semantics/4.1.0: + resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} + dev: false + + /http-proxy-agent/4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /http-proxy-agent/5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /https-proxy-agent/5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: false + + /humanize-ms/1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: false + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /iconv-lite/0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + optional: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore-walk/4.0.1: + resolution: {integrity: sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==} + engines: {node: '>=10'} + dependencies: + minimatch: 3.1.2 + dev: false + + /ignore/5.1.9: + resolution: {integrity: sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==} + engines: {node: '>= 4'} + dev: false + + /ignore/5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: false + + /import-lazy/4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: false + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: false + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: false + + /infer-owner/1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: false + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + + /info-symbol/0.1.0: + resolution: {integrity: sha512-qkc9wjLDQ+dYYZnY5uJXGNNHyZ0UOMDUnhvy0SEZGVVYmQ5s4i8cPAin2MbU6OxJgi8dfj/AnwqPx0CJE6+Lsw==} + engines: {node: '>=0.10.0'} + dev: false + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /inquirer-autocomplete-prompt/1.4.0_inquirer@8.2.5: + resolution: {integrity: sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==} + engines: {node: '>=10'} + peerDependencies: + inquirer: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + inquirer: 8.2.5 + run-async: 2.4.1 + rxjs: 6.6.7 + dev: false + + /inquirer/7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + dev: false + + /inquirer/8.2.5: + resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: false + + /ip/2.0.0: + resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: false + + /is-accessor-descriptor/0.1.6: + resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /is-accessor-descriptor/1.0.0: + resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + dev: false + + /is-buffer/1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: false + + /is-data-descriptor/0.1.4: + resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /is-data-descriptor/1.0.0: + resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + dev: false + + /is-descriptor/0.1.6: + resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 0.1.6 + is-data-descriptor: 0.1.4 + kind-of: 5.1.0 + dev: false + + /is-descriptor/1.0.2: + resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 1.0.0 + is-data-descriptor: 1.0.0 + kind-of: 6.0.3 + dev: false + + /is-even/1.0.0: + resolution: {integrity: sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==} + engines: {node: '>=0.10.0'} + dependencies: + is-odd: 0.1.2 + dev: false + + /is-extendable/0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-extendable/1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: false + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: false + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + + /is-interactive/1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: false + + /is-lambda/1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + dev: false + + /is-lower-case/1.1.3: + resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} + dependencies: + lower-case: 1.1.4 + dev: false + + /is-number/2.1.0: + resolution: {integrity: sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /is-number/3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /is-number/4.0.0: + resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: false + + /is-odd/0.1.2: + resolution: {integrity: sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + dev: false + + /is-path-cwd/2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + dev: false + + /is-path-inside/3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: false + + /is-plain-obj/2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: false + + /is-plain-object/2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + + /is-self-closing/1.0.1: + resolution: {integrity: sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg==} + engines: {node: '>=0.12.0'} + dependencies: + self-closing-tags: 1.0.1 + dev: false + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + + /is-unicode-supported/0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: false + + /is-upper-case/1.1.2: + resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} + dependencies: + upper-case: 1.1.3 + dev: false + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: false + + /isarray/1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + + /isbinaryfile/4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + dev: false + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /isobject/0.2.0: + resolution: {integrity: sha512-VaWq6XYAsbvM0wf4dyBO7WH9D7GosB7ZZlqrawI9BBiTMINBeCyqSKBa35m870MY3O4aM31pYyZi9DfGrYMJrQ==} + engines: {node: '>=0.10.0'} + dev: false + + /isobject/2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: false + + /isobject/3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: false + + /jju/1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: false + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + + /jsonfile/4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.10 + dev: false + + /jsonparse/1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: false + + /kind-of/3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: false + + /kind-of/4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: false + + /kind-of/5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + dev: false + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + + /lazy-cache/2.0.2: + resolution: {integrity: sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==} + engines: {node: '>=0.10.0'} + dependencies: + set-getter: 0.1.1 + dev: false + + /lilconfig/2.0.4: + resolution: {integrity: sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==} + engines: {node: '>=10'} + dev: false + + /lilconfig/2.0.6: + resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} + engines: {node: '>=10'} + dev: false + + /lint-staged/12.3.4: + resolution: {integrity: sha512-yv/iK4WwZ7/v0GtVkNb3R82pdL9M+ScpIbJLJNyCXkJ1FGaXvRCOg/SeL59SZtPpqZhE7BD6kPKFLIDUhDx2/w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dependencies: + cli-truncate: 3.1.0 + colorette: 2.0.19 + commander: 8.3.0 + debug: 4.3.4_supports-color@9.3.1 + execa: 5.1.1 + lilconfig: 2.0.4 + listr2: 4.0.5 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-inspect: 1.12.3 + string-argv: 0.3.1 + supports-color: 9.3.1 + yaml: 1.10.2 + transitivePeerDependencies: + - enquirer + dev: false + + /listr2/4.0.5: + resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} + engines: {node: '>=12'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.19 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.0 + rxjs: 7.8.0 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: false + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: false + + /lodash._reinterpolate/3.0.0: + resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + dev: false + + /lodash.get/4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: false + + /lodash.isequal/4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash.template/4.5.0: + resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + dependencies: + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 + dev: false + + /lodash.templatesettings/4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + dependencies: + lodash._reinterpolate: 3.0.0 + dev: false + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /log-ok/0.1.1: + resolution: {integrity: sha512-cc8VrkS6C+9TFuYAwuHpshrcrGRAv7d0tUJ0GdM72ZBlKXtlgjUZF84O+OhQUdiVHoF7U/nVxwpjOdwUJ8d3Vg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-green: 0.1.1 + success-symbol: 0.1.0 + dev: false + + /log-symbols/4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: false + + /log-update/4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: false + + /log-utils/0.2.1: + resolution: {integrity: sha512-udyegKoMz9eGfpKAX//Khy7sVAZ8b1F7oLDnepZv/1/y8xTvsyPgqQrM94eG8V0vcc2BieYI2kVW4+aa6m+8Qw==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-colors: 0.2.0 + error-symbol: 0.1.0 + info-symbol: 0.1.0 + log-ok: 0.1.1 + success-symbol: 0.1.0 + time-stamp: 1.1.0 + warning-symbol: 0.1.0 + dev: false + + /logging-helpers/1.0.0: + resolution: {integrity: sha512-qyIh2goLt1sOgQQrrIWuwkRjUx4NUcEqEGAcYqD8VOnOC6ItwkrVE8/tA4smGpjzyp4Svhc6RodDp9IO5ghpyA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + log-utils: 0.2.1 + dev: false + + /lower-case-first/1.0.2: + resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} + dependencies: + lower-case: 1.1.4 + dev: false + + /lower-case/1.1.4: + resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /lru-cache/7.14.1: + resolution: {integrity: sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==} + engines: {node: '>=12'} + dev: false + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + + /make-fetch-happen/10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + agentkeepalive: 4.2.1 + cacache: 16.1.3 + http-cache-semantics: 4.1.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.14.1 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /make-fetch-happen/9.1.0: + resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} + engines: {node: '>= 10'} + dependencies: + agentkeepalive: 4.2.1 + cacache: 15.3.0 + http-cache-semantics: 4.1.0 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 1.4.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 6.2.1 + ssri: 8.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /map-cache/0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: false + + /map-visit/1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + dev: false + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: false + + /micromatch/3.1.10: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + dev: false + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: false + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: false + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: false + + /minimatch/5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + dev: false + + /minipass-collect/1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /minipass-fetch/1.4.1: + resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: false + + /minipass-fetch/2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: false + + /minipass-flush/1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /minipass-json-stream/1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + dependencies: + jsonparse: 1.3.1 + minipass: 3.3.6 + dev: false + + /minipass-pipeline/1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: false + + /minipass-sized/1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: false + + /minipass/3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass/4.0.0: + resolution: {integrity: sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minizlib/2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + + /mixin-deep/1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + dev: false + + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.7 + dev: false + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /moment/2.29.4: + resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + dev: false + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /mute-stream/0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: false + + /nanomatch/1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + dev: false + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /no-case/2.3.2: + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + dependencies: + lower-case: 1.1.4 + dev: false + + /node-gyp/8.4.1: + resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} + engines: {node: '>= 10.12.0'} + hasBin: true + dependencies: + env-paths: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.10 + make-fetch-happen: 9.1.0 + nopt: 5.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.3.8 + tar: 6.1.13 + which: 2.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /node-plop/0.26.3: + resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} + engines: {node: '>=8.9.4'} + dependencies: + '@babel/runtime-corejs3': 7.20.7 + '@types/inquirer': 6.5.0 + change-case: 3.1.0 + del: 5.1.0 + globby: 10.0.2 + handlebars: 4.7.7 + inquirer: 7.3.3 + isbinaryfile: 4.0.10 + lodash.get: 4.4.2 + mkdirp: 0.5.6 + resolve: 1.22.1 + dev: false + + /nopt/5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /npm-bundled/1.1.2: + resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} + dependencies: + npm-normalize-package-bin: 1.0.1 + dev: false + + /npm-install-checks/4.0.0: + resolution: {integrity: sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==} + engines: {node: '>=10'} + dependencies: + semver: 7.3.8 + dev: false + + /npm-normalize-package-bin/1.0.1: + resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} + dev: false + + /npm-package-arg/8.1.5: + resolution: {integrity: sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + semver: 7.3.8 + validate-npm-package-name: 3.0.0 + dev: false + + /npm-packlist/3.0.0: + resolution: {integrity: sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + glob: 7.2.3 + ignore-walk: 4.0.1 + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 + dev: false + + /npm-pick-manifest/6.1.1: + resolution: {integrity: sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==} + dependencies: + npm-install-checks: 4.0.0 + npm-normalize-package-bin: 1.0.1 + npm-package-arg: 8.1.5 + semver: 7.3.8 + dev: false + + /npm-registry-fetch/12.0.2: + resolution: {integrity: sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + dependencies: + make-fetch-happen: 10.2.1 + minipass: 3.3.6 + minipass-fetch: 1.4.1 + minipass-json-stream: 1.0.1 + minizlib: 2.1.2 + npm-package-arg: 8.1.5 + transitivePeerDependencies: + - supports-color + dev: false + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: false + + /npmlog/6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + dev: false + + /object-copy/0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + dev: false + + /object-inspect/1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: false + + /object-visit/1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + + /object.pick/1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: false + + /ora/5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.7.0 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: false + + /os-tmpdir/1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: false + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: false + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: false + + /p-map/3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + dependencies: + aggregate-error: 3.1.0 + dev: false + + /p-map/4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: false + + /pacote/12.0.3: + resolution: {integrity: sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + hasBin: true + dependencies: + '@npmcli/git': 2.1.0 + '@npmcli/installed-package-contents': 1.0.7 + '@npmcli/promise-spawn': 1.3.2 + '@npmcli/run-script': 2.0.0 + cacache: 15.3.0 + chownr: 2.0.0 + fs-minipass: 2.1.0 + infer-owner: 1.0.4 + minipass: 3.3.6 + mkdirp: 1.0.4 + npm-package-arg: 8.1.5 + npm-packlist: 3.0.0 + npm-pick-manifest: 6.1.1 + npm-registry-fetch: 12.0.2 + promise-retry: 2.0.1 + read-package-json-fast: 2.0.3 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.1.13 + transitivePeerDependencies: + - supports-color + dev: false + + /param-case/2.1.1: + resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} + dependencies: + no-case: 2.3.2 + dev: false + + /pascal-case/2.0.1: + resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} + dependencies: + camel-case: 3.0.0 + upper-case-first: 1.1.2 + dev: false + + /pascalcase/0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + dev: false + + /path-case/2.1.1: + resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} + dependencies: + no-case: 2.3.2 + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: false + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: false + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: false + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: false + + /posix-character-classes/0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + dev: false + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /promise-inflight/1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + dev: false + + /promise-retry/2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + dev: false + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: false + + /read-package-json-fast/2.0.3: + resolution: {integrity: sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==} + engines: {node: '>=10'} + dependencies: + json-parse-even-better-errors: 2.3.1 + npm-normalize-package-bin: 1.0.1 + dev: false + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + + /regex-not/1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + dev: false + + /relative/3.0.2: + resolution: {integrity: sha512-Q5W2qeYtY9GbiR8z1yHNZ1DGhyjb4AnLEjt8iE6XfcC1QIu+FAtj3HQaO0wH28H1mX6cqNLvAqWhP402dxJGyA==} + engines: {node: '>= 0.8.0'} + dependencies: + isobject: 2.1.0 + dev: false + + /remarkable/1.7.4: + resolution: {integrity: sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==} + engines: {node: '>= 0.10.0'} + hasBin: true + dependencies: + argparse: 1.0.10 + autolinker: 0.28.1 + dev: false + + /repeat-element/1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + dev: false + + /repeat-string/1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: false + + /require-directory/2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /resolve-url/0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + dev: false + + /resolve/1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + dependencies: + path-parse: 1.0.7 + dev: false + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /restore-cursor/3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: false + + /ret/0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: false + + /retry/0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + dev: false + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: false + + /rfdc/1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: false + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: false + + /run-async/2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: false + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: false + + /rush-archive-project-plugin/1.1.3: + resolution: {integrity: sha512-duxYLiETHIs/uB5g7Fiu3GEsfypqeOoOdYF3091v9TRg9cVvAiw4RkhLk8tLgynDGsFcz4xD1XnkMMYJ8VPkiQ==} + hasBin: true + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + inquirer: 8.2.5 + ora: 5.4.1 + tar: 6.1.13 + yargs: 17.3.1 + dev: false + + /rush-audit-cache-plugin/0.0.2: + resolution: {integrity: sha512-texnPnt6UTW585gd7VIP7NnSQ0Nank/tJGMScH5yBnvfPtdVAG/nwyvVZXBv1BQbC7pwfy9nE3b65mBEVygj3A==} + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + commander: 9.4.1 + ignore: 5.1.9 + dev: false + + /rush-init-project-plugin/0.6.0_typescript@4.4.2: + resolution: {integrity: sha512-tC+hbPgb8yPMuK1yr1al+w0dnjnpn29mjio4CP0e+KhHpRAI3Ph339C45JqpGfl+y6spZzpg6yq6iaUoMrGjPw==} + hasBin: true + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + chalk: 4.1.2 + commander: 9.4.1 + handlebars-helpers: 0.10.0 + inquirer: 8.2.5 + inquirer-autocomplete-prompt: 1.4.0_inquirer@8.2.5 + lilconfig: 2.0.6 + lodash: 4.17.21 + node-plop: 0.26.3 + ora: 5.4.1 + sort-package-json: 1.54.0 + tapable: 2.2.1 + ts-node: 10.4.0_typescript@4.4.2 + validate-npm-package-name: 3.0.0 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript + dev: false + + /rush-lint-staged-plugin/0.1.6: + resolution: {integrity: sha512-4P33F4bajVeldZYHVH1f9PCWuxGk8KTP+V8RUgUrujT4nnjHwqmK1G46e8sDskyq9LmnVEMZsqEWz2spY803RA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + '@rushstack/node-core-library': 3.44.1 + lint-staged: 12.3.4 + transitivePeerDependencies: + - enquirer + dev: false + + /rush-sort-package-json/0.0.3: + resolution: {integrity: sha512-spyFsIRGsJXKzkKy/K7c90cTyfxV+jgIAS3JG/LmTzfuK6Or7tghBvhBZIhCiA03+FC978SX+qc/5l+zcSBD8Q==} + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + sort-package-json: 1.54.0 + dev: false + + /rush-upgrade-self-plugin/1.0.6: + resolution: {integrity: sha512-WN2Sk8LClYNktNlnkDWFtBS7k2o/V5yaN+bBoNnP0CG12h3weXZ/D/XU0fKzIBn1AikNy01MGKUGfbjmby56QA==} + hasBin: true + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + fast-glob: 3.2.12 + find-up: 5.0.0 + inquirer: 8.2.5 + ora: 5.4.1 + pacote: 12.0.3 + transitivePeerDependencies: + - supports-color + dev: false + + /rxjs/6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: false + + /rxjs/7.8.0: + resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} + dependencies: + tslib: 2.4.1 + dev: false + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-regex/1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + dependencies: + ret: 0.1.15 + dev: false + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /self-closing-tags/1.0.1: + resolution: {integrity: sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA==} + engines: {node: '>=0.12.0'} + dev: false + + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /sentence-case/2.1.1: + resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} + dependencies: + no-case: 2.3.2 + upper-case-first: 1.1.2 + dev: false + + /set-blocking/2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + + /set-getter/0.1.1: + resolution: {integrity: sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==} + engines: {node: '>=0.10.0'} + dependencies: + to-object-path: 0.3.0 + dev: false + + /set-value/2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + dev: false + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: false + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: false + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: false + + /slice-ansi/3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: false + + /slice-ansi/4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: false + + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: false + + /smart-buffer/4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + + /snake-case/2.1.0: + resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} + dependencies: + no-case: 2.3.2 + dev: false + + /snapdragon-node/2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + dev: false + + /snapdragon-util/3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /snapdragon/0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + dev: false + + /socks-proxy-agent/6.2.1: + resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socks-proxy-agent/7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socks/2.7.1: + resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 2.0.0 + smart-buffer: 4.2.0 + dev: false + + /sort-object-keys/1.1.3: + resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} + dev: false + + /sort-package-json/1.54.0: + resolution: {integrity: sha512-MA0nRiSfZ4/CNM/9rz70Hwq4PpvtBc3v532tzQSmoaLSdeBB3cCd488xmNruLL0fb/ZdbKlcaDDudwnrObbjBw==} + hasBin: true + dependencies: + detect-indent: 6.1.0 + detect-newline: 3.1.0 + git-hooks-list: 1.0.3 + globby: 10.0.0 + is-plain-obj: 2.1.0 + sort-object-keys: 1.1.3 + dev: false + + /source-map-resolve/0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + dev: false + + /source-map-url/0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + dev: false + + /source-map/0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: false + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + + /split-string/3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + dev: false + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /ssri/8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /ssri/9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + dev: false + + /static-extend/0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + dev: false + + /string-argv/0.3.1: + resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} + engines: {node: '>=0.6.19'} + dev: false + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string-width/5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 + dev: false + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: false + + /striptags/3.2.0: + resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==} + dev: false + + /success-symbol/0.1.0: + resolution: {integrity: sha512-7S6uOTxPklNGxOSbDIg4KlVLBQw1UiGVyfCUYgYxrZUKRblUkmGj7r8xlfQoFudvqLv6Ap5gd76/IIFfI9JG2A==} + engines: {node: '>=0.10.0'} + dev: false + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false + + /supports-color/9.3.1: + resolution: {integrity: sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==} + engines: {node: '>=12'} + dev: false + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /swap-case/1.1.2: + resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} + dependencies: + lower-case: 1.1.4 + upper-case: 1.1.3 + dev: false + + /tapable/2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: false + + /tar/6.1.13: + resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 4.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + + /through/2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: false + + /through2/2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.7 + xtend: 4.0.2 + dev: false + + /time-stamp/1.1.0: + resolution: {integrity: sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==} + engines: {node: '>=0.10.0'} + dev: false + + /timsort/0.3.0: + resolution: {integrity: sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==} + dev: false + + /title-case/2.1.1: + resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /tmp/0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: false + + /to-gfm-code-block/0.1.1: + resolution: {integrity: sha512-LQRZWyn8d5amUKnfR9A9Uu7x9ss7Re8peuWR2gkh1E+ildOfv2aF26JpuDg8JtvCduu5+hOrMIH+XstZtnagqg==} + engines: {node: '>=0.10.0'} + dev: false + + /to-object-path/0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /to-regex-range/2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + dev: false + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: false + + /to-regex/3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + dev: false + + /ts-node/10.4.0_typescript@4.4.2: + resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.7.0 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + acorn: 8.8.1 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.4.2 + yn: 3.1.1 + dev: false + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: false + + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: false + + /typeof-article/0.1.1: + resolution: {integrity: sha512-Vn42zdX3FhmUrzEmitX3iYyLb+Umwpmv8fkZRIknYh84lmdrwqZA5xYaoKiIj2Rc5i/5wcDrpUmZcbk1U51vTw==} + engines: {node: '>=4'} + dependencies: + kind-of: 3.2.2 + dev: false + + /typescript/4.4.2: + resolution: {integrity: sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: false + + /uglify-js/3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /union-value/1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + dev: false + + /unique-filename/1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + dependencies: + unique-slug: 2.0.2 + dev: false + + /unique-filename/2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + unique-slug: 3.0.0 + dev: false + + /unique-slug/2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + dependencies: + imurmurhash: 0.1.4 + dev: false + + /unique-slug/3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + dev: false + + /universalify/0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: false + + /unset-value/1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + dev: false + + /upper-case-first/1.1.2: + resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} + dependencies: + upper-case: 1.1.3 + dev: false + + /upper-case/1.1.3: + resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} + dev: false + + /urix/0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + dev: false + + /use/3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + dev: false + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /validate-npm-package-name/3.0.0: + resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} + dependencies: + builtins: 1.0.3 + dev: false + + /validator/13.7.0: + resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} + engines: {node: '>= 0.10'} + dev: false + + /validator/8.2.0: + resolution: {integrity: sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==} + engines: {node: '>= 0.10'} + dev: false + + /warning-symbol/0.1.0: + resolution: {integrity: sha512-1S0lwbHo3kNUKA4VomBAhqn4DPjQkIKSdbOin5K7EFUQNwyIKx+wZMGXKI53RUjla8V2B8ouQduUlgtx8LoSMw==} + engines: {node: '>=0.10.0'} + dev: false + + /wcwidth/1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: false + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /wide-align/1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false + + /wordwrap/1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + + /wrap-ansi/6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrap-ansi/7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: false + + /y18n/5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + + /yargs-parser/21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs/17.3.1: + resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + + /year/0.2.1: + resolution: {integrity: sha512-9GnJUZ0QM4OgXuOzsKNzTJ5EOkums1Xc+3YQXp+Q+UxFjf7zLucp9dQ8QMIft0Szs1E1hUiXFim1OYfEKFq97w==} + engines: {node: '>=0.8'} + dev: false + + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: false + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: false + + /z-schema/3.18.4: + resolution: {integrity: sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 8.2.0 + optionalDependencies: + commander: 2.20.3 + dev: false + + /z-schema/5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.7.0 + optionalDependencies: + commander: 9.4.1 + dev: false diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-archive-project-plugin/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-archive-project-plugin/command-line.json new file mode 100644 index 0000000..41555bb --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-archive-project-plugin/command-line.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "archive-project", + "commandKind": "global", + "summary": "Archives the project to a tar file", + "shellCommand": "rush-project-archiver archive", + "safeForSimultaneousRushProcesses": true + }, + { + "name": "unarchive-project", + "commandKind": "global", + "summary": "Unarchive the project from a tar file", + "shellCommand": "rush-project-archiver unarchive", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "description": "The name of the package", + "longName": "--package-name", + "argumentName": "PACKAGE_NAME", + "associatedCommands": ["archive-project", "unarchive-project"], + "required": true + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..7f32f98 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-archive-project-plugin", + "description": "Rush plugin to archive project", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-audit-cache-plugin/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-audit-cache-plugin/command-line.json new file mode 100644 index 0000000..3a80f67 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-audit-cache-plugin/command-line.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "audit-cache", + "commandKind": "global", + "summary": "Audit cache configuration by diagnosing the build processes of the target project and its dependencies", + "shellCommand": "node /lib/bin.js", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "description": "The package name of the project", + "longName": "--project", + "shortName": "-p", + "argumentName": "PACKAGE_NAME", + "associatedCommands": [ "audit-cache" ], + "required": false + }, + { + "parameterKind": "string", + "description": "verbosity that can be increased", + "longName": "--verbose", + "shortName": "-v", + "argumentName": "VERBOSE", + "associatedCommands": [ "audit-cache" ], + "required": false + }, + { + "parameterKind": "flag", + "description": "show current version", + "longName": "--version", + "shortName": "-V", + "associatedCommands": [ "audit-cache" ], + "required": false + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..8ba3aa8 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-audit-cache-plugin", + "description": "A diagnostic tool for rush build cache", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-init-project-plugin/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-init-project-plugin/command-line.json new file mode 100644 index 0000000..5bad04d --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-init-project-plugin/command-line.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "init-project", + "commandKind": "global", + "summary": "Initialize project in this monorepo", + "shellCommand": "rush-init-project", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "description": "Provide predefined answers with JSON string", + "shortName": "-a", + "longName": "--answer", + "argumentName": "ANSWER", + "associatedCommands": ["init-project"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Provide the option isDryRun in plugin context", + "shortName": "-d", + "longName": "--dry-run", + "associatedCommands": ["init-project"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Provide verbose log output", + "shortName": "-v", + "longName": "--verbose", + "associatedCommands": ["init-project"], + "required": false + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..2d39526 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-init-project-plugin", + "description": "Rush plugin for initialize project in monorepo", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-lint-staged-plugin/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-lint-staged-plugin/command-line.json new file mode 100644 index 0000000..ad4c779 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-lint-staged-plugin/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "lint-staged", + "commandKind": "global", + "summary": "Rush plugin for lint-staged", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..4d41939 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-lint-staged-plugin", + "description": "Rush plugin for lint-staged", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json new file mode 100644 index 0000000..2ff4b5f --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-sort-package-json", + "description": "Rush plugin for sort package.json file in the project", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-sort-package-json/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-sort-package-json/command-line.json new file mode 100644 index 0000000..5fdf60c --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-sort-package-json/rush-sort-package-json/command-line.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "sort-package-json", + "commandKind": "global", + "summary": "Rush plugin for sort package.json file in the project", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] +} \ No newline at end of file diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json b/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..452ef53 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-upgrade-self-plugin", + "description": "Rush plugin for upgrade Rush itself", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-upgrade-self-plugin/command-line.json b/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-upgrade-self-plugin/command-line.json new file mode 100644 index 0000000..276e127 --- /dev/null +++ b/common/autoinstallers/command-plugins/rush-plugins/rush-upgrade-self-plugin/rush-upgrade-self-plugin/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "upgrade-self", + "commandKind": "global", + "summary": "Upgrade Rush.js itself", + "shellCommand": "rush-upgrade-self", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/common/autoinstallers/rush-prettier/package.json b/common/autoinstallers/rush-prettier/package.json new file mode 100644 index 0000000..ce4353c --- /dev/null +++ b/common/autoinstallers/rush-prettier/package.json @@ -0,0 +1,9 @@ +{ + "name": "rush-prettier", + "version": "1.0.0", + "private": true, + "dependencies": { + "pretty-quick": "3.1.3", + "prettier": "2.7.1" + } +} diff --git a/common/autoinstallers/rush-prettier/pnpm-lock.yaml b/common/autoinstallers/rush-prettier/pnpm-lock.yaml new file mode 100644 index 0000000..e392fd8 --- /dev/null +++ b/common/autoinstallers/rush-prettier/pnpm-lock.yaml @@ -0,0 +1,296 @@ +lockfileVersion: 5.3 + +specifiers: + prettier: 2.7.1 + pretty-quick: 3.1.3 + +dependencies: + prettier: 2.7.1 + pretty-quick: 3.1.3_prettier@2.7.1 + +packages: + + /@types/minimatch/3.0.5: + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + dev: false + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /array-differ/3.0.0: + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} + dev: false + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: false + + /arrify/2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: false + + /chalk/3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: false + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: false + + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + + /execa/4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: false + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + + /get-stream/5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: false + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: false + + /human-signals/1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: false + + /ignore/5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: false + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: false + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: false + + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + + /multimatch/4.0.0: + resolution: {integrity: sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==} + engines: {node: '>=8'} + dependencies: + '@types/minimatch': 3.0.5 + array-differ: 3.0.0 + array-union: 2.1.0 + arrify: 2.0.1 + minimatch: 3.1.2 + dev: false + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: false + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: false + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: false + + /prettier/2.7.1: + resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: false + + /pretty-quick/3.1.3_prettier@2.7.1: + resolution: {integrity: sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==} + engines: {node: '>=10.13'} + hasBin: true + peerDependencies: + prettier: '>=2.0.0' + dependencies: + chalk: 3.0.0 + execa: 4.1.0 + find-up: 4.1.0 + ignore: 5.2.4 + mri: 1.2.0 + multimatch: 4.0.0 + prettier: 2.7.1 + dev: false + + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: false + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: false + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: false + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false diff --git a/common/config/rush/.npmrc b/common/config/rush/.npmrc new file mode 100644 index 0000000..c5980e6 --- /dev/null +++ b/common/config/rush/.npmrc @@ -0,0 +1,22 @@ +# Rush uses this file to configure the NPM package registry during installation. It is applicable +# to PNPM, NPM, and Yarn package managers. It is used by operations such as "rush install", +# "rush update", and the "install-run.js" scripts. +# +# NOTE: The "rush publish" command uses .npmrc-publish instead. +# +# Before invoking the package manager, Rush will copy this file to the folder where installation +# is performed. The copied file will omit any config lines that reference environment variables +# that are undefined in that session; this avoids problems that would otherwise result due to +# a missing variable being replaced by an empty string. +# +# * * * SECURITY WARNING * * * +# +# It is NOT recommended to store authentication tokens in a text file on a lab machine, because +# other unrelated processes may be able to read the file. Also, the file may persist indefinitely, +# for example if the machine loses power. A safer practice is to pass the token via an +# environment variable, which can be referenced from .npmrc using ${} expansion. For example: +# +# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} +# +registry=https://registry.npmjs.org/ +always-auth=false diff --git a/common/config/rush/.npmrc-publish b/common/config/rush/.npmrc-publish new file mode 100644 index 0000000..5c84bbe --- /dev/null +++ b/common/config/rush/.npmrc-publish @@ -0,0 +1,23 @@ +# This config file is very similar to common/config/rush/.npmrc, except that .npmrc-publish +# is used by the "rush publish" command, as publishing often involves different credentials +# and registries than other operations. +# +# Before invoking the package manager, Rush will copy this file to "common/temp/publish-home/.npmrc" +# and then temporarily map that folder as the "home directory" for the current user account. +# This enables the same settings to apply for each project folder that gets published. The copied file +# will omit any config lines that reference environment variables that are undefined in that session; +# this avoids problems that would otherwise result due to a missing variable being replaced by +# an empty string. +# +# * * * SECURITY WARNING * * * +# +# It is NOT recommended to store authentication tokens in a text file on a lab machine, because +# other unrelated processes may be able to read the file. Also, the file may persist indefinitely, +# for example if the machine loses power. A safer practice is to pass the token via an +# environment variable, which can be referenced from .npmrc using ${} expansion. For example: +# +# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} +# +registry=https://registry.npmjs.org/ +always-auth=true +//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} \ No newline at end of file diff --git a/common/config/rush/.pnpmfile.cjs b/common/config/rush/.pnpmfile.cjs new file mode 100644 index 0000000..9456174 --- /dev/null +++ b/common/config/rush/.pnpmfile.cjs @@ -0,0 +1,38 @@ +'use strict'; + +/** + * When using the PNPM package manager, you can use pnpmfile.js to workaround + * dependencies that have mistakes in their package.json file. (This feature is + * functionally similar to Yarn's "resolutions".) + * + * For details, see the PNPM documentation: + * https://pnpm.js.org/docs/en/hooks.html + * + * IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE + * ANY CACHED DEPENDENCY ANALYSIS. After any modification to pnpmfile.js, it's recommended to run + * "rush update --full" so that PNPM will recalculate all version selections. + */ +module.exports = { + hooks: { + readPackage + } +}; + +/** + * This hook is invoked during installation before a package's dependencies + * are selected. + * The `packageJson` parameter is the deserialized package.json + * contents for the package that is about to be installed. + * The `context` parameter provides a log() function. + * The return value is the updated object. + */ +function readPackage(packageJson, context) { + + // // The karma types have a missing dependency on typings from the log4js package. + // if (packageJson.name === '@types/karma') { + // context.log('Fixed up dependencies for @types/karma'); + // packageJson.dependencies['log4js'] = '0.6.38'; + // } + + return packageJson; +} diff --git a/common/config/rush/artifactory.json b/common/config/rush/artifactory.json new file mode 100644 index 0000000..65f7da0 --- /dev/null +++ b/common/config/rush/artifactory.json @@ -0,0 +1,85 @@ +/** + * This configuration file manages Rush integration with JFrog Artifactory services. + * More documentation is available on the Rush website: https://rushjs.io + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/artifactory.schema.json", + + "packageRegistry": { + /** + * (Required) Set this to "true" to enable Rush to manage tokens for an Artifactory NPM registry. + * When enabled, "rush install" will automatically detect when the user's ~/.npmrc + * authentication token is missing or expired. And "rush setup" will prompt the user to + * renew their token. + * + * The default value is false. + */ + "enabled": false, + + /** + * (Required) Specify the URL of your NPM registry. This is the same URL that appears in + * your .npmrc file. It should look something like this example: + * + * https://your-company.jfrog.io/your-project/api/npm/npm-private/ + */ + "registryUrl": "", + + /** + * A list of custom strings that "rush setup" should add to the user's ~/.npmrc file at the time + * when the token is updated. This could be used for example to configure the company registry + * to be used whenever NPM is invoked as a standalone command (but it's not needed for Rush + * operations like "rush add" and "rush install", which get their mappings from the monorepo's + * common/config/rush/.npmrc file). + * + * NOTE: The ~/.npmrc settings are global for the user account on a given machine, so be careful + * about adding settings that may interfere with other work outside the monorepo. + */ + "userNpmrcLinesToAdd": [ + // "@example:registry=https://your-company.jfrog.io/your-project/api/npm/npm-private/" + ], + + /** + * (Required) Specifies the URL of the Artifactory control panel where the user can generate + * an API key. This URL is printed after the "visitWebsite" message. + * It should look something like this example: https://your-company.jfrog.io/ + * Specify an empty string to suppress this line entirely. + */ + "artifactoryWebsiteUrl": "", + + /** + * These settings allow the "rush setup" interactive prompts to be customized, for + * example with messages specific to your team or configuration. Specify an empty string + * to suppress that message entirely. + */ + "messageOverrides": { + /** + * Overrides the message that normally says: + * "This monorepo consumes packages from an Artifactory private NPM registry." + */ + // "introduction": "", + /** + * Overrides the message that normally says: + * "Please contact the repository maintainers for help with setting up an Artifactory user account." + */ + // "obtainAnAccount": "", + /** + * Overrides the message that normally says: + * "Please open this URL in your web browser:" + * + * The "artifactoryWebsiteUrl" string is printed after this message. + */ + // "visitWebsite": "", + /** + * Overrides the message that normally says: + * "Your user name appears in the upper-right corner of the JFrog website." + */ + // "locateUserName": "", + /** + * Overrides the message that normally says: + * "Click 'Edit Profile' on the JFrog website. Click the 'Generate API Key' + * button if you haven't already done so previously." + */ + // "locateApiKey": "" + } + } +} diff --git a/common/config/rush/build-cache.json b/common/config/rush/build-cache.json new file mode 100644 index 0000000..04cdd9c --- /dev/null +++ b/common/config/rush/build-cache.json @@ -0,0 +1,84 @@ +/** + * This configuration file manages Rush's build cache feature. + * More documentation is available on the Rush website: https://rushjs.io + */ + { + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/build-cache.schema.json", + + /** + * (Required) EXPERIMENTAL - Set this to true to enable the build cache feature. + * + * See https://rushjs.io/pages/maintainer/build_cache/ for details about this experimental feature. + */ + "buildCacheEnabled": false, + + /** + * (Required) Choose where project build outputs will be cached. + * + * Possible values: "local-only", "azure-blob-storage", "amazon-s3" + */ + "cacheProvider": "local-only", + + /** + * Setting this property overrides the cache entry ID. If this property is set, it must contain + * a [hash] token. It may also contain a [projectName] or a [projectName:normalize] token. + */ + // "cacheEntryNamePattern": "[projectName:normalize]-[hash]" + + /** + * Use this configuration with "cacheProvider"="azure-blob-storage" + */ + "azureBlobStorageConfiguration": { + /** + * (Required) The name of the the Azure storage account to use for build cache. + */ + // "storageAccountName": "example", + + /** + * (Required) The name of the container in the Azure storage account to use for build cache. + */ + // "storageContainerName": "my-container", + + /** + * The Azure environment the storage account exists in. Defaults to AzurePublicCloud. + * + * Possible values: "AzurePublicCloud", "AzureChina", "AzureGermany", "AzureGovernment" + */ + // "azureEnvironment": "AzurePublicCloud", + + /** + * An optional prefix for cache item blob names. + */ + // "blobPrefix": "my-prefix", + + /** + * If set to true, allow writing to the cache. Defaults to false. + */ + // "isCacheWriteAllowed": true + }, + + /** + * Use this configuration with "cacheProvider"="amazon-s3" + */ + "amazonS3Configuration": { + /** + * (Required) The Amazon S3 region of the bucket to use for build cache (e.g. "us-east-1"). + */ + // "s3Region": "us-east-1", + + /** + * The name of the bucket in Amazon S3 to use for build cache. + */ + // (Required) "s3Bucket": "my-bucket", + + /** + * An optional prefix ("folder") for cache items. + */ + // "s3Prefix": "my-prefix", + + /** + * If set to true, allow writing to the cache. Defaults to false. + */ + // "isCacheWriteAllowed": true + } +} diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json new file mode 100644 index 0000000..987b2f5 --- /dev/null +++ b/common/config/rush/command-line.json @@ -0,0 +1,344 @@ +/** + * This configuration file defines custom commands for the "rush" command-line. + * More documentation is available on the Rush website: https://rushjs.io + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + + /** + * Custom "commands" introduce new verbs for the command-line. To see the help for these + * example commands, try "rush --help", "rush my-bulk-command --help", or + * "rush my-global-command --help". + */ + "commands": [ + { + "name": "prettier", + "commandKind": "global", + "summary": "Used by the pre-commit Git hook. This command invokes Prettier to reformat staged changes.", + + "autoinstallerName": "rush-prettier", + + // This will invoke common/autoinstall/rush-prettier/node_modules/.bin/pretty-quick + "shellCommand": "pretty-quick --staged", + + "safeForSimultaneousRushProcesses": true + }, + { + "commandKind": "bulk", + "name": "test", + "summary": "Bulk test script", + "description": "This is an command that runs test script separately for each project", + "safeForSimultaneousRushProcesses": false, + "enableParallelism": true, + "ignoreDependencyOrder": false, + "ignoreMissingScript": false, + "allowWarningsInSuccessfulBuild": false, + "incremental": false, + "watchForChanges": false, + "disableBuildCache": false + } + // { + // /** + // * (Required) Determines the type of custom command. + // * Rush's "bulk" commands are invoked separately for each project. Rush will look in + // * each project's package.json file for a "scripts" entry whose name matches the + // * command name. By default, the command will run for every project in the repo, + // * according to the dependency graph (similar to how "rush build" works). + // * The set of projects can be restricted e.g. using the "--to" or "--from" parameters. + // */ + // "commandKind": "bulk", + // + // /** + // * (Required) The name that will be typed as part of the command line. This is also the name + // * of the "scripts" hook in the project's package.json file. + // * The name should be comprised of lower case words separated by hyphens or colons. The name should include an + // * English verb (e.g. "deploy"). Use a hyphen to separate words (e.g. "upload-docs"). A group of related commands + // * can be prefixed with a colon (e.g. "docs:generate", "docs:deploy", "docs:serve", etc). + // * + // * Note that if the "rebuild" command is overridden here, it becomes separated from the "build" command + // * and will call the "rebuild" script instead of the "build" script. + // */ + // "name": "my-bulk-command", + // + // /** + // * (Required) A short summary of the custom command to be shown when printing command line + // * help, e.g. "rush --help". + // */ + // "summary": "Example bulk custom command", + // + // /** + // * A detailed description of the command to be shown when printing command line + // * help (e.g. "rush --help my-command"). + // * If omitted, the "summary" text will be shown instead. + // * + // * Whenever you introduce commands/parameters, taking a little time to write meaningful + // * documentation can make a big difference for the developer experience in your repo. + // */ + // "description": "This is an example custom command that runs separately for each project", + // + // /** + // * By default, Rush operations acquire a lock file which prevents multiple commands from executing simultaneously + // * in the same repo folder. (For example, it would be a mistake to run "rush install" and "rush build" at the + // * same time.) If your command makes sense to run concurrently with other operations, + // * set "safeForSimultaneousRushProcesses" to true to disable this protection. + // * + // * In particular, this is needed for custom scripts that invoke other Rush commands. + // */ + // "safeForSimultaneousRushProcesses": false, + // + // /** + // * (Required) If true, then this command is safe to be run in parallel, i.e. executed + // * simultaneously for multiple projects. Similar to "rush build", regardless of parallelism + // * projects will not start processing until their dependencies have completed processing. + // */ + // "enableParallelism": false, + // + // /** + // * Normally projects will be processed according to their dependency order: a given project will not start + // * processing the command until all of its dependencies have completed. This restriction doesn't apply for + // * certain operations, for example a "clean" task that deletes output files. In this case + // * you can set "ignoreDependencyOrder" to true to increase parallelism. + // */ + // "ignoreDependencyOrder": false, + // + // /** + // * Normally Rush requires that each project's package.json has a "scripts" entry matching + // * the custom command name. To disable this check, set "ignoreMissingScript" to true; + // * projects with a missing definition will be skipped. + // */ + // "ignoreMissingScript": false, + // + // /** + // * When invoking shell scripts, Rush uses a heuristic to distinguish errors from warnings: + // * - If the shell script returns a nonzero process exit code, Rush interprets this as "one or more errors". + // * Error output is displayed in red, and it prevents Rush from attempting to process any downstream projects. + // * - If the shell script returns a zero process exit code but writes something to its stderr stream, + // * Rush interprets this as "one or more warnings". Warning output is printed in yellow, but does NOT prevent + // * Rush from processing downstream projects. + // * + // * Thus, warnings do not interfere with local development, but they will cause a CI job to fail, because + // * the Rush process itself returns a nonzero exit code if there are any warnings or errors. This is by design. + // * In an active monorepo, we've found that if you allow any warnings in your master branch, it inadvertently + // * teaches developers to ignore warnings, which quickly leads to a situation where so many "expected" warnings + // * have accumulated that warnings no longer serve any useful purpose. + // * + // * Sometimes a poorly behaved task will write output to stderr even though its operation was successful. + // * In that case, it's strongly recommended to fix the task. However, as a workaround you can set + // * allowWarningsInSuccessfulBuild=true, which causes Rush to return a nonzero exit code for errors only. + // * + // * Note: The default value is false. In Rush 5.7.x and earlier, the default value was true. + // */ + // "allowWarningsInSuccessfulBuild": false, + // + // /** + // * If true then this command will be incremental like the built-in "build" command + // */ + // "incremental": false, + // + // /** + // * (EXPERIMENTAL) Normally Rush terminates after the command finishes. If this option is set to "true" Rush + // * will instead enter a loop where it watches the file system for changes to the selected projects. Whenever a + // * change is detected, the command will be invoked again for the changed project and any selected projects that + // * directly or indirectly depend on it. + // * + // * For details, refer to the website article "Using watch mode". + // */ + // "watchForChanges": false, + // + // /** + // * (EXPERIMENTAL) Disable cache for this action. This may be useful if this command affects state outside of + // * projects' own folders. + // */ + // "disableBuildCache": false + // }, + // + // { + // /** + // * (Required) Determines the type of custom command. + // * Rush's "global" commands are invoked once for the entire repo. + // */ + // "commandKind": "global", + // + // "name": "my-global-command", + // "summary": "Example global custom command", + // "description": "This is an example custom command that runs once for the entire repo", + // + // "safeForSimultaneousRushProcesses": false, + // + // /** + // * (Required) A script that will be invoked using the OS shell. The working directory will be + // * the folder that contains rush.json. If custom parameters are associated with this command, their + // * values will be appended to the end of this string. + // */ + // "shellCommand": "node common/scripts/my-global-command.js", + // + // /** + // * If your "shellCommand" script depends on NPM packages, the recommended best practice is + // * to make it into a regular Rush project that builds using your normal toolchain. In cases where + // * the command needs to work without first having to run "rush build", the recommended practice + // * is to publish the project to an NPM registry and use common/scripts/install-run.js to launch it. + // * + // * Autoinstallers offer another possibility: They are folders under "common/autoinstallers" with + // * a package.json file and shrinkwrap file. Rush will automatically invoke the package manager to + // * install these dependencies before an associated command is invoked. Autoinstallers have the + // * advantage that they work even in a branch where "rush install" is broken, which makes them a + // * good solution for Git hook scripts. But they have the disadvantages of not being buildable + // * projects, and of increasing the overall installation footprint for your monorepo. + // * + // * The "autoinstallerName" setting must not contain a path and must be a valid NPM package name. + // * For example, the name "my-task" would map to "common/autoinstallers/my-task/package.json", and + // * the "common/autoinstallers/my-task/node_modules/.bin" folder would be added to the shell PATH when + // * invoking the "shellCommand". + // */ + // // "autoinstallerName": "my-task" + // } + ], + + /** + * Custom "parameters" introduce new parameters for specified Rush command-line commands. + * For example, you might define a "--production" parameter for the "rush build" command. + */ + "parameters": [ + // { + // /** + // * (Required) Determines the type of custom parameter. + // * A "flag" is a custom command-line parameter whose presence acts as an on/off switch. + // */ + // "parameterKind": "flag", + // + // /** + // * (Required) The long name of the parameter. It must be lower-case and use dash delimiters. + // */ + // "longName": "--my-flag", + // + // /** + // * An optional alternative short name for the parameter. It must be a dash followed by a single + // * lower-case or upper-case letter, which is case-sensitive. + // * + // * NOTE: The Rush developers recommend that automation scripts should always use the long name + // * to improve readability. The short name is only intended as a convenience for humans. + // * The alphabet letters run out quickly, and are difficult to memorize, so *only* use + // * a short name if you expect the parameter to be needed very often in everyday operations. + // */ + // "shortName": "-m", + // + // /** + // * (Required) A long description to be shown in the command-line help. + // * + // * Whenever you introduce commands/parameters, taking a little time to write meaningful + // * documentation can make a big difference for the developer experience in your repo. + // */ + // "description": "A custom flag parameter that is passed to the scripts that are invoked when building projects", + // + // /** + // * (Required) A list of custom commands and/or built-in Rush commands that this parameter may + // * be used with. The parameter will be appended to the shell command that Rush invokes. + // */ + // "associatedCommands": ["build", "rebuild"] + // }, + // + // { + // /** + // * (Required) Determines the type of custom parameter. + // * A "string" is a custom command-line parameter whose value is a simple text string. + // */ + // "parameterKind": "string", + // "longName": "--my-string", + // "description": "A custom string parameter for the \"my-global-command\" custom command", + // + // "associatedCommands": ["my-global-command"], + // + // /** + // * The name of the argument, which will be shown in the command-line help. + // * + // * For example, if the parameter name is '--count" and the argument name is "NUMBER", + // * then the command-line help would display "--count NUMBER". The argument name must + // * be comprised of upper-case letters, numbers, and underscores. It should be kept short. + // */ + // "argumentName": "SOME_TEXT", + // + // /** + // * If true, this parameter must be included with the command. The default is false. + // */ + // "required": false + // }, + // + // { + // /** + // * (Required) Determines the type of custom parameter. + // * A "choice" is a custom command-line parameter whose argument must be chosen from a list of + // * allowable alternatives. + // */ + // "parameterKind": "choice", + // "longName": "--my-choice", + // "description": "A custom choice parameter for the \"my-global-command\" custom command", + // + // "associatedCommands": ["my-global-command"], + // + // /** + // * If true, this parameter must be included with the command. The default is false. + // */ + // "required": false, + // + // /** + // * Normally if a parameter is omitted from the command line, it will not be passed + // * to the shell command. this value will be inserted by default. Whereas if a "defaultValue" + // * is defined, the parameter will always be passed to the shell command, and will use the + // * default value if unspecified. The value must be one of the defined alternatives. + // */ + // "defaultValue": "vanilla", + // + // /** + // * (Required) A list of alternative argument values that can be chosen for this parameter. + // */ + // "alternatives": [ + // { + // /** + // * A token that is one of the alternatives that can be used with the choice parameter, + // * e.g. "vanilla" in "--flavor vanilla". + // */ + // "name": "vanilla", + // + // /** + // * A detailed description for the alternative that can be shown in the command-line help. + // * + // * Whenever you introduce commands/parameters, taking a little time to write meaningful + // * documentation can make a big difference for the developer experience in your repo. + // */ + // "description": "Use the vanilla flavor (the default)" + // }, + // + // { + // "name": "chocolate", + // "description": "Use the chocolate flavor" + // }, + // + // { + // "name": "strawberry", + // "description": "Use the strawberry flavor" + // } + // ] + // } + { + "longName": "--no-color", + "parameterKind": "flag", + "description": "disable colors in the build log, defaults to 'true'", + // "associatedPhases": ["_phase:build", "_phase:test"], + "associatedCommands": ["build", "rebuild", "test"] + }, + { + "longName": "--update-snapshots", + "parameterKind": "flag", + "description": "Update Jest snapshots", + // "associatedPhases": ["_phase:test"], + "associatedCommands": ["test"] + }, + { + "longName": "--production", + "parameterKind": "flag", + "description": "Perform a production build, including minification and localization steps", + // "associatedPhases": ["_phase:build", "_phase:test"], + "associatedCommands": ["build", "rebuild", "test"] + } + ] +} diff --git a/common/config/rush/common-versions.json b/common/config/rush/common-versions.json new file mode 100644 index 0000000..1df9ccf --- /dev/null +++ b/common/config/rush/common-versions.json @@ -0,0 +1,62 @@ +/** + * This configuration file specifies NPM dependency version selections that affect all projects + * in a Rush repo. More documentation is available on the Rush website: https://rushjs.io + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json", + + /** + * A table that specifies a "preferred version" for a given NPM package. This feature is typically used + * to hold back an indirect dependency to a specific older version, or to reduce duplication of indirect dependencies. + * + * The "preferredVersions" value can be any SemVer range specifier (e.g. "~1.2.3"). Rush injects these values into + * the "dependencies" field of the top-level common/temp/package.json, which influences how the package manager + * will calculate versions. The specific effect depends on your package manager. Generally it will have no + * effect on an incompatible or already constrained SemVer range. If you are using PNPM, similar effects can be + * achieved using the pnpmfile.js hook. See the Rush documentation for more details. + * + * After modifying this field, it's recommended to run "rush update --full" so that the package manager + * will recalculate all version selections. + */ + "preferredVersions": { + /** + * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo, + * instead of the latest version. + */ + // "some-library": "1.2.3" + }, + + /** + * When set to true, for all projects in the repo, all dependencies will be automatically added as preferredVersions, + * except in cases where different projects specify different version ranges for a given dependency. For older + * package managers, this tended to reduce duplication of indirect dependencies. However, it can sometimes cause + * trouble for indirect dependencies with incompatible peerDependencies ranges. + * + * The default value is true. If you're encountering installation errors related to peer dependencies, + * it's recommended to set this to false. + * + * After modifying this field, it's recommended to run "rush update --full" so that the package manager + * will recalculate all version selections. + */ + // "implicitlyPreferredVersions": false, + + /** + * The "rush check" command can be used to enforce that every project in the repo must specify + * the same SemVer range for a given dependency. However, sometimes exceptions are needed. + * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be + * accepted by "rush check" for a given dependency. + * + * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE + * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO). + * This design avoids unnecessary churn in this file. + */ + "allowedAlternativeVersions": { + /** + * For example, allow some projects to use an older TypeScript compiler + * (in addition to whatever "usual" version is being used by other projects in the repo): + */ + // "typescript": [ + // "~2.4.0" + // ] + } +} diff --git a/common/config/rush/experiments.json b/common/config/rush/experiments.json new file mode 100644 index 0000000..2657ac0 --- /dev/null +++ b/common/config/rush/experiments.json @@ -0,0 +1,38 @@ +/** + * This configuration file allows repo maintainers to enable and disable experimental + * Rush features. More documentation is available on the Rush website: https://rushjs.io + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/experiments.schema.json", + + /** + * By default, 'rush install' passes --no-prefer-frozen-lockfile to 'pnpm install'. + * Set this option to true to pass '--frozen-lockfile' instead for faster installs. + */ + // "usePnpmFrozenLockfileForRushInstall": true, + + /** + * By default, 'rush update' passes --no-prefer-frozen-lockfile to 'pnpm install'. + * Set this option to true to pass '--prefer-frozen-lockfile' instead to minimize shrinkwrap changes. + */ + // "usePnpmPreferFrozenLockfileForRushUpdate": true, + + /** + * If using the 'preventManualShrinkwrapChanges' option, restricts the hash to only include the layout of external dependencies. + * Used to allow links between workspace projects or the addition/removal of references to existing dependency versions to not + * cause hash changes. + */ + // "omitImportersFromPreventManualShrinkwrapChanges": true, + + /** + * If true, the chmod field in temporary project tar headers will not be normalized. + * This normalization can help ensure consistent tarball integrity across platforms. + */ + // "noChmodFieldInTarHeaderNormalization": true, + + /** + * If true, build caching will respect the allowWarningsInSuccessfulBuild flag and cache builds with warnings. + * This will not replay warnings from the cached build. + */ + // "buildCacheWithAllowWarningsInSuccessfulBuild": true +} diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml new file mode 100644 index 0000000..de6dfbe --- /dev/null +++ b/common/config/rush/pnpm-lock.yaml @@ -0,0 +1,7957 @@ +lockfileVersion: 5.3 + +importers: + + .: + specifiers: {} + + ../../rush-plugins/rush-archive-project-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': ~0.1.53 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/heft-jest': 1.0.1 + '@types/inquirer': ~8.1.3 + '@types/json2md': ~1.5.1 + '@types/node': 12.20.24 + '@types/pacote': ~11.1.1 + '@types/tar': ~6.1.1 + '@types/yargs': ~17.0.7 + eslint: 7.32.0 + inquirer: ~8.2.0 + json2md: ~2.0.0 + ora: 5.4.1 + tar: ~6.1.11 + typescript: 4.4.2 + yargs: ~17.3.0 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + inquirer: 8.2.0 + json2md: 2.0.0 + ora: 5.4.1 + tar: 6.1.11 + yargs: 17.3.0 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': 0.1.53_@rushstack+heft@0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/inquirer': 8.1.3 + '@types/json2md': 1.5.1 + '@types/node': 12.20.24 + '@types/pacote': 11.1.1 + '@types/tar': 6.1.1 + '@types/yargs': 17.0.7 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-audit-cache-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': ~0.1.53 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + commander: ~9.4.0 + eslint: 7.32.0 + ignore: 5.1.9 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + commander: 9.4.0 + ignore: 5.1.9 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': 0.1.53_@rushstack+heft@0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-git-lfs-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': ~0.1.53 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/fs-extra': ~9.0.13 + '@types/heft-jest': 1.0.1 + '@types/minimatch': ~5.1.2 + '@types/node': 12.20.24 + chalk: 4.1.2 + commander: ~9.4.0 + eslint: 7.32.0 + execa: ~5.1.1 + fs-extra: ~10.1.0 + minimatch: ~5.1.1 + ora: 5.4.1 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + chalk: 4.1.2 + commander: 9.4.0 + execa: 5.1.1 + fs-extra: 10.1.0 + minimatch: 5.1.1 + ora: 5.4.1 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': 0.1.53_@rushstack+heft@0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/fs-extra': 9.0.13 + '@types/heft-jest': 1.0.1 + '@types/minimatch': 5.1.2 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-init-project-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': ~0.1.53 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/blessed': ~0.1.19 + '@types/ejs': ~3.1.1 + '@types/heft-jest': 1.0.1 + '@types/inquirer': ~8.1.3 + '@types/inquirer-autocomplete-prompt': ~3.0.0 + '@types/lodash': 4.14.184 + '@types/node': 12.20.24 + blessed: ~0.1.81 + blessed-contrib: ~4.11.0 + chalk: 4.1.2 + commander: ~9.4.0 + del: 6.1.1 + ejs: ~3.1.8 + eslint: 7.32.0 + handlebars-helpers: ~0.10.0 + inquirer: ~8.2.0 + inquirer-autocomplete-prompt: ~1.4.0 + lilconfig: ~2.0.4 + lodash: 4.17.21 + node-plop: 0.26.3 + ora: 5.4.1 + sort-package-json: 1.54.0 + tapable: ~2.2.1 + ts-node: ~10.4.0 + typescript: 4.4.2 + validate-npm-package-name: ~3.0.0 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/inquirer-autocomplete-prompt': 3.0.0 + blessed: 0.1.81 + blessed-contrib: 4.11.0 + chalk: 4.1.2 + commander: 9.4.0 + handlebars-helpers: 0.10.0 + inquirer: 8.2.0 + inquirer-autocomplete-prompt: 1.4.0_inquirer@8.2.0 + lilconfig: 2.0.4 + lodash: 4.17.21 + node-plop: 0.26.3 + ora: 5.4.1 + sort-package-json: 1.54.0 + tapable: 2.2.1 + ts-node: 10.4.0_06c0d17a2604b53f6f8299daedda05cf + validate-npm-package-name: 3.0.0 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': 0.1.53_@rushstack+heft@0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/blessed': 0.1.19 + '@types/ejs': 3.1.1 + '@types/heft-jest': 1.0.1 + '@types/inquirer': 8.1.3 + '@types/lodash': 4.14.184 + '@types/node': 12.20.24 + del: 6.1.1 + ejs: 3.1.8 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-lint-staged-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + lint-staged: 12.3.4 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + lint-staged: 12.3.4 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-print-log-if-error-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-sort-package-json: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + sort-package-json: 1.54.0 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + sort-package-json: 1.54.0 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/node': 12.20.24 + eslint: 7.32.0 + typescript: 4.4.2 + + ../../rush-plugins/rush-upgrade-self-plugin: + specifiers: + '@rushstack/eslint-config': 2.4.5 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31 + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + '@types/heft-jest': 1.0.1 + '@types/inquirer': ~8.1.3 + '@types/node': 12.20.24 + '@types/pacote': ~11.1.1 + eslint: 7.32.0 + fast-glob: ~3.2.7 + find-up: 5.0.0 + inquirer: ~8.2.0 + ora: 5.4.1 + pacote: ~12.0.2 + typescript: 4.4.2 + dependencies: + '@rushstack/node-core-library': 3.44.1 + '@rushstack/rush-sdk': 5.62.4 + fast-glob: 3.2.7 + find-up: 5.0.0 + inquirer: 8.2.0 + ora: 5.4.1 + pacote: 12.0.2 + devDependencies: + '@rushstack/eslint-config': 2.4.5_eslint@7.32.0+typescript@4.4.2 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-node-rig': 1.2.31_@rushstack+heft@0.43.2 + '@types/heft-jest': 1.0.1 + '@types/inquirer': 8.1.3 + '@types/node': 12.20.24 + '@types/pacote': 11.1.1 + eslint: 7.32.0 + typescript: 4.4.2 + +packages: + + /@babel/code-frame/7.12.11: + resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} + dependencies: + '@babel/highlight': 7.16.0 + dev: true + + /@babel/code-frame/7.16.0: + resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.16.0 + dev: true + + /@babel/compat-data/7.16.4: + resolution: {integrity: sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.16.0: + resolution: {integrity: sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.0 + '@babel/generator': 7.16.0 + '@babel/helper-compilation-targets': 7.16.3_@babel+core@7.16.0 + '@babel/helper-module-transforms': 7.16.0 + '@babel/helpers': 7.16.3 + '@babel/parser': 7.16.4 + '@babel/template': 7.16.0 + '@babel/traverse': 7.16.3 + '@babel/types': 7.16.0 + convert-source-map: 1.8.0 + debug: 4.3.3 + gensync: 1.0.0-beta.2 + json5: 2.2.0 + semver: 6.3.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator/7.16.0: + resolution: {integrity: sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + jsesc: 2.5.2 + source-map: 0.5.7 + dev: true + + /@babel/helper-compilation-targets/7.16.3_@babel+core@7.16.0: + resolution: {integrity: sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.16.4 + '@babel/core': 7.16.0 + '@babel/helper-validator-option': 7.14.5 + browserslist: 4.18.1 + semver: 6.3.0 + dev: true + + /@babel/helper-function-name/7.16.0: + resolution: {integrity: sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-get-function-arity': 7.16.0 + '@babel/template': 7.16.0 + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-get-function-arity/7.16.0: + resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-hoist-variables/7.16.0: + resolution: {integrity: sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-member-expression-to-functions/7.16.0: + resolution: {integrity: sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-module-imports/7.16.0: + resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-module-transforms/7.16.0: + resolution: {integrity: sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-module-imports': 7.16.0 + '@babel/helper-replace-supers': 7.16.0 + '@babel/helper-simple-access': 7.16.0 + '@babel/helper-split-export-declaration': 7.16.0 + '@babel/helper-validator-identifier': 7.15.7 + '@babel/template': 7.16.0 + '@babel/traverse': 7.16.3 + '@babel/types': 7.16.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-optimise-call-expression/7.16.0: + resolution: {integrity: sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-plugin-utils/7.14.5: + resolution: {integrity: sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-replace-supers/7.16.0: + resolution: {integrity: sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-member-expression-to-functions': 7.16.0 + '@babel/helper-optimise-call-expression': 7.16.0 + '@babel/traverse': 7.16.3 + '@babel/types': 7.16.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access/7.16.0: + resolution: {integrity: sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-split-export-declaration/7.16.0: + resolution: {integrity: sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@babel/helper-validator-identifier/7.15.7: + resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option/7.14.5: + resolution: {integrity: sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers/7.16.3: + resolution: {integrity: sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.16.0 + '@babel/traverse': 7.16.3 + '@babel/types': 7.16.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight/7.16.0: + resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.15.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser/7.16.4: + resolution: {integrity: sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: true + + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.16.0: + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.16.0: + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.16.0: + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.16.0: + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.16.0: + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.16.0: + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + dev: true + + /@babel/runtime-corejs3/7.16.5: + resolution: {integrity: sha512-F1pMwvTiUNSAM8mc45kccMQxj31x3y3P+tA/X8hKNWp3/hUsxdGxZ3D3H8JIkxtfA8qGkaBTKvcmvStaYseAFw==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.20.1 + regenerator-runtime: 0.13.9 + dev: false + + /@babel/template/7.16.0: + resolution: {integrity: sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.0 + '@babel/parser': 7.16.4 + '@babel/types': 7.16.0 + dev: true + + /@babel/traverse/7.16.3: + resolution: {integrity: sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.0 + '@babel/generator': 7.16.0 + '@babel/helper-function-name': 7.16.0 + '@babel/helper-hoist-variables': 7.16.0 + '@babel/helper-split-export-declaration': 7.16.0 + '@babel/parser': 7.16.4 + '@babel/types': 7.16.0 + debug: 4.3.3 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types/7.16.0: + resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.15.7 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage/0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@cnakazawa/watch/1.0.4: + resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} + engines: {node: '>=0.1.95'} + hasBin: true + dependencies: + exec-sh: 0.3.6 + minimist: 1.2.5 + dev: true + + /@colors/colors/1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: false + optional: true + + /@cspotcode/source-map-consumer/0.8.0: + resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==} + engines: {node: '>= 12'} + dev: false + + /@cspotcode/source-map-support/0.7.0: + resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==} + engines: {node: '>=12'} + dependencies: + '@cspotcode/source-map-consumer': 0.8.0 + dev: false + + /@eslint/eslintrc/0.4.3: + resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.3 + espree: 7.3.1 + globals: 13.12.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + js-yaml: 3.14.1 + minimatch: 3.0.4 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@gar/promisify/1.1.2: + resolution: {integrity: sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==} + dev: false + + /@humanwhocodes/config-array/0.5.0: + resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.3 + minimatch: 3.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@istanbuljs/load-nyc-config/1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema/0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console/25.5.0: + resolution: {integrity: sha512-T48kZa6MK1Y6k4b89sexwmSF4YLeZS/Udqg3Jj3jG/cHH+N/sLFCEoXEDMOKugJQ9FxPN1osxIknvKkxt6MKyw==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + chalk: 3.0.0 + jest-message-util: 25.5.0 + jest-util: 25.5.0 + slash: 3.0.0 + dev: true + + /@jest/core/25.4.0: + resolution: {integrity: sha512-h1x9WSVV0+TKVtATGjyQIMJENs8aF6eUjnCoi4jyRemYZmekLr8EJOGQqTWEX8W6SbZ6Skesy9pGXrKeAolUJw==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/console': 25.5.0 + '@jest/reporters': 25.4.0 + '@jest/test-result': 25.5.0 + '@jest/transform': 25.5.1 + '@jest/types': 25.5.0 + ansi-escapes: 4.3.2 + chalk: 3.0.0 + exit: 0.1.2 + graceful-fs: 4.2.8 + jest-changed-files: 25.5.0 + jest-config: 25.5.4 + jest-haste-map: 25.5.1 + jest-message-util: 25.5.0 + jest-regex-util: 25.2.6 + jest-resolve: 25.5.1 + jest-resolve-dependencies: 25.5.4 + jest-runner: 25.5.4 + jest-runtime: 25.5.4 + jest-snapshot: 25.5.1 + jest-util: 25.5.0 + jest-validate: 25.5.0 + jest-watcher: 25.5.0 + micromatch: 4.0.4 + p-each-series: 2.2.0 + realpath-native: 2.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@jest/environment/25.5.0: + resolution: {integrity: sha512-U2VXPEqL07E/V7pSZMSQCvV5Ea4lqOlT+0ZFijl/i316cRMHvZ4qC+jBdryd+lmRetjQo0YIQr6cVPNxxK87mA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/fake-timers': 25.5.0 + '@jest/types': 25.5.0 + jest-mock: 25.5.0 + dev: true + + /@jest/fake-timers/25.5.0: + resolution: {integrity: sha512-9y2+uGnESw/oyOI3eww9yaxdZyHq7XvprfP/eeoCsjqKYts2yRlsHS/SgjPDV8FyMfn2nbMy8YzUk6nyvdLOpQ==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + jest-message-util: 25.5.0 + jest-mock: 25.5.0 + jest-util: 25.5.0 + lolex: 5.1.2 + dev: true + + /@jest/globals/25.5.2: + resolution: {integrity: sha512-AgAS/Ny7Q2RCIj5kZ+0MuKM1wbF0WMLxbCVl/GOMoCNbODRdJ541IxJ98xnZdVSZXivKpJlNPIWa3QmY0l4CXA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/environment': 25.5.0 + '@jest/types': 25.5.0 + expect: 25.5.0 + dev: true + + /@jest/reporters/25.4.0: + resolution: {integrity: sha512-bhx/buYbZgLZm4JWLcRJ/q9Gvmd3oUh7k2V7gA4ZYBx6J28pIuykIouclRdiAC6eGVX1uRZT+GK4CQJLd/PwPg==} + engines: {node: '>= 8.3'} + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 25.5.0 + '@jest/test-result': 25.5.0 + '@jest/transform': 25.5.1 + '@jest/types': 25.5.0 + chalk: 3.0.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.0 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 4.0.3 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.1 + jest-haste-map: 25.5.1 + jest-resolve: 25.5.1 + jest-util: 25.5.0 + jest-worker: 25.5.0 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 3.1.0 + terminal-link: 2.1.1 + v8-to-istanbul: 4.1.4 + optionalDependencies: + node-notifier: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/source-map/25.5.0: + resolution: {integrity: sha512-eIGx0xN12yVpMcPaVpjXPnn3N30QGJCJQSkEDUt9x1fI1Gdvb07Ml6K5iN2hG7NmMP6FDmtPEssE3z6doOYUwQ==} + engines: {node: '>= 8.3'} + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.8 + source-map: 0.6.1 + dev: true + + /@jest/test-result/25.5.0: + resolution: {integrity: sha512-oV+hPJgXN7IQf/fHWkcS99y0smKLU2czLBJ9WA0jHITLst58HpQMtzSYxzaBvYc6U5U6jfoMthqsUlUlbRXs0A==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/console': 25.5.0 + '@jest/types': 25.5.0 + '@types/istanbul-lib-coverage': 2.0.3 + collect-v8-coverage: 1.0.1 + dev: true + + /@jest/test-sequencer/25.5.4: + resolution: {integrity: sha512-pTJGEkSeg1EkCO2YWq6hbFvKNXk8ejqlxiOg1jBNLnWrgXOkdY6UmqZpwGFXNnRt9B8nO1uWMzLLZ4eCmhkPNA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/test-result': 25.5.0 + graceful-fs: 4.2.8 + jest-haste-map: 25.5.1 + jest-runner: 25.5.4 + jest-runtime: 25.5.4 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@jest/transform/25.4.0: + resolution: {integrity: sha512-t1w2S6V1sk++1HHsxboWxPEuSpN8pxEvNrZN+Ud/knkROWtf8LeUmz73A4ezE8476a5AM00IZr9a8FO9x1+j3g==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/core': 7.16.0 + '@jest/types': 25.5.0 + babel-plugin-istanbul: 6.1.1 + chalk: 3.0.0 + convert-source-map: 1.8.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.8 + jest-haste-map: 25.5.1 + jest-regex-util: 25.2.6 + jest-util: 25.5.0 + micromatch: 4.0.4 + pirates: 4.0.4 + realpath-native: 2.0.0 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/transform/25.5.1: + resolution: {integrity: sha512-Y8CEoVwXb4QwA6Y/9uDkn0Xfz0finGkieuV0xkdF9UtZGJeLukD5nLkaVrVsODB1ojRWlaoD0AJZpVHCSnJEvg==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/core': 7.16.0 + '@jest/types': 25.5.0 + babel-plugin-istanbul: 6.1.1 + chalk: 3.0.0 + convert-source-map: 1.8.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.8 + jest-haste-map: 25.5.1 + jest-regex-util: 25.2.6 + jest-util: 25.5.0 + micromatch: 4.0.4 + pirates: 4.0.4 + realpath-native: 2.0.0 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types/25.5.0: + resolution: {integrity: sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==} + engines: {node: '>= 8.3'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + '@types/istanbul-reports': 1.1.2 + '@types/yargs': 15.0.14 + chalk: 3.0.0 + dev: true + + /@jest/types/27.4.2: + resolution: {integrity: sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + '@types/istanbul-reports': 3.0.1 + '@types/node': 12.20.24 + '@types/yargs': 16.0.4 + chalk: 4.1.2 + dev: true + + /@microsoft/api-extractor-model/7.13.16: + resolution: {integrity: sha512-ttdxVXsTWL5dd26W1YNLe3LgDsE0EE273aZlcLe58W0opymBybCYU1Mn+OHQM8BuErrdvdN8LdpWAAbkiOEN/Q==} + dependencies: + '@microsoft/tsdoc': 0.13.2 + '@microsoft/tsdoc-config': 0.15.2 + '@rushstack/node-core-library': 3.43.2 + dev: true + + /@microsoft/api-extractor/7.18.19: + resolution: {integrity: sha512-aY+/XR7PtQXtnqNPFRs3/+iVRlQJpo6uLTjO2g7PqmnMywl3GBU3bCgAlV/khZtAQbIs6Le57XxmSE6rOqbcfg==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.13.16 + '@microsoft/tsdoc': 0.13.2 + '@microsoft/tsdoc-config': 0.15.2 + '@rushstack/node-core-library': 3.43.2 + '@rushstack/rig-package': 0.3.5 + '@rushstack/ts-command-line': 4.10.4 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.17.0 + semver: 7.3.5 + source-map: 0.6.1 + typescript: 4.4.2 + dev: true + + /@microsoft/tsdoc-config/0.15.2: + resolution: {integrity: sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==} + dependencies: + '@microsoft/tsdoc': 0.13.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true + + /@microsoft/tsdoc/0.13.2: + resolution: {integrity: sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==} + dev: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + + /@npmcli/fs/1.0.0: + resolution: {integrity: sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==} + dependencies: + '@gar/promisify': 1.1.2 + semver: 7.3.5 + dev: false + + /@npmcli/git/2.1.0: + resolution: {integrity: sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==} + dependencies: + '@npmcli/promise-spawn': 1.3.2 + lru-cache: 6.0.0 + mkdirp: 1.0.4 + npm-pick-manifest: 6.1.1 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.3.5 + which: 2.0.2 + dev: false + + /@npmcli/installed-package-contents/1.0.7: + resolution: {integrity: sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==} + engines: {node: '>= 10'} + hasBin: true + dependencies: + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 + dev: false + + /@npmcli/move-file/1.1.2: + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: false + + /@npmcli/node-gyp/1.0.3: + resolution: {integrity: sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==} + dev: false + + /@npmcli/promise-spawn/1.3.2: + resolution: {integrity: sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==} + dependencies: + infer-owner: 1.0.4 + dev: false + + /@npmcli/run-script/2.0.0: + resolution: {integrity: sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==} + dependencies: + '@npmcli/node-gyp': 1.0.3 + '@npmcli/promise-spawn': 1.3.2 + node-gyp: 8.4.1 + read-package-json-fast: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@rushstack/eslint-config/2.4.5_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-MilTlXhJMvJhsud/Sb+otph/JTLuoUQYO/MK6SCiGsoCWlIOgbw+JKUjs4viu6Kocd0VqfbNCXFqWRqCbdq4DA==} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 + typescript: '>=3.0.0' + dependencies: + '@rushstack/eslint-patch': 1.1.0 + '@rushstack/eslint-plugin': 0.8.3_eslint@7.32.0+typescript@4.4.2 + '@rushstack/eslint-plugin-packlets': 0.3.3_eslint@7.32.0+typescript@4.4.2 + '@rushstack/eslint-plugin-security': 0.2.3_eslint@7.32.0+typescript@4.4.2 + '@typescript-eslint/eslint-plugin': 4.31.2_326168addec61fdd42b406abb1a8f069 + '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.2 + '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.2 + '@typescript-eslint/typescript-estree': 4.31.2_typescript@4.4.2 + eslint: 7.32.0 + eslint-plugin-promise: 4.2.1 + eslint-plugin-react: 7.20.6_eslint@7.32.0 + eslint-plugin-tsdoc: 0.2.14 + typescript: 4.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@rushstack/eslint-patch/1.1.0: + resolution: {integrity: sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==} + dev: true + + /@rushstack/eslint-plugin-packlets/0.3.3_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-6fslCsfk1mZho4uBsnywCO5Jzj7I21V1OKt40ZxbLO7LrMccm9orUYJiy5dI3Lx6NQtczuYrtqp8Xqp0ur9KPA==} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 + dependencies: + '@rushstack/tree-pattern': 0.2.2 + '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.2 + eslint: 7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@rushstack/eslint-plugin-security/0.2.3_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-OnngkJCx91og1U8a8gus2g+r5OOtkQ8Tpo8jcGrtI6YpIIujqLM6lIe7XM3e+iumYdKnnOAVs3NH14BN9rlIoQ==} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 + dependencies: + '@rushstack/tree-pattern': 0.2.2 + '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.2 + eslint: 7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@rushstack/eslint-plugin/0.8.3_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-LUXUv9oUDHghe73HHIqDxJAqCYBsvKcbg+2KRs/aNczNZzoaXKJPLS6YvlCBiuI1XNq/eLEX7L/LPnKfbe+1Yw==} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 + dependencies: + '@rushstack/tree-pattern': 0.2.2 + '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.2 + eslint: 7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@rushstack/heft-config-file/0.7.6: + resolution: {integrity: sha512-GwU/q5ITs+VS/cSIoUz+fdiH4qwqJGS1MF9p8+X7ni9JlloxBBbZqUFceYh3JcYSAmSUD/ltai0sY2Qnjt6KTQ==} + engines: {node: '>=10.13.0'} + dependencies: + '@rushstack/node-core-library': 3.43.2 + '@rushstack/rig-package': 0.3.5 + jsonpath-plus: 4.0.0 + dev: true + + /@rushstack/heft-config-file/0.7.9: + resolution: {integrity: sha512-h9cWk7HOBRXVDhR2tciieIRmiT0Mi1flE5LYA3VZqAqSo9c9KrjUwXyXH/RSYI1f7RFNYrJ2wbOieL/WJXkfKA==} + engines: {node: '>=10.13.0'} + dependencies: + '@rushstack/node-core-library': 3.44.2 + '@rushstack/rig-package': 0.3.6 + jsonpath-plus: 4.0.0 + dev: true + + /@rushstack/heft-jest-plugin/0.1.47_@rushstack+heft@0.43.2: + resolution: {integrity: sha512-P2oyGoZP8XVIpWvmKW88bo2oPkkJteFqSytbqELDI9eYjyHFViyT4Axk4TOq9ANOHe0k0J4lPJmApfJQAeY5Zw==} + peerDependencies: + '@rushstack/heft': ^0.42.3 + dependencies: + '@jest/core': 25.4.0 + '@jest/reporters': 25.4.0 + '@jest/transform': 25.4.0 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-config-file': 0.7.6 + '@rushstack/node-core-library': 3.43.2 + jest-config: 25.4.0 + jest-snapshot: 25.4.0 + lodash: 4.17.21 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@rushstack/heft-jest-plugin/0.1.53_@rushstack+heft@0.43.2: + resolution: {integrity: sha512-iLDJDlXFjSvAv/CoEXhCcIhYed+WEK/gr72073QH/oQ2NWoEHWjdQQen7O1o4vS51BuJe1n74/btKCi2VsrigA==} + peerDependencies: + '@rushstack/heft': ^0.43.2 + dependencies: + '@jest/core': 25.4.0 + '@jest/reporters': 25.4.0 + '@jest/transform': 25.4.0 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-config-file': 0.7.9 + '@rushstack/node-core-library': 3.44.2 + jest-config: 25.4.0 + jest-snapshot: 25.4.0 + lodash: 4.17.21 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@rushstack/heft-node-rig/1.2.31_@rushstack+heft@0.43.2: + resolution: {integrity: sha512-R40gFljWV9ZOgYxZQ1u65LSpK0i1Nw37k5PxL8P/h6HahaAlWOwnTJNcsUY+vNpuZEd5PM/lxaxDrWIKFfKsMw==} + peerDependencies: + '@rushstack/heft': ^0.42.3 + dependencies: + '@microsoft/api-extractor': 7.18.19 + '@rushstack/heft': 0.43.2 + '@rushstack/heft-jest-plugin': 0.1.47_@rushstack+heft@0.43.2 + eslint: 7.30.0 + typescript: 4.4.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@rushstack/heft/0.43.2: + resolution: {integrity: sha512-LBP6nKmBcYJvGMVXkSIiGfv9Z2AAB3QPOsvpBBQIZVxwMDxC/UFuAz/bdqbAIh70ZdkRo1OqIKqTWl15LHOVvw==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + '@rushstack/heft-config-file': 0.7.9 + '@rushstack/node-core-library': 3.44.2 + '@rushstack/rig-package': 0.3.6 + '@rushstack/ts-command-line': 4.10.5 + '@types/tapable': 1.0.6 + argparse: 1.0.10 + chokidar: 3.4.3 + fast-glob: 3.2.11 + glob: 7.0.6 + glob-escape: 0.0.2 + prettier: 2.3.2 + semver: 7.3.5 + tapable: 1.1.3 + true-case-path: 2.2.1 + dev: true + + /@rushstack/node-core-library/3.43.2: + resolution: {integrity: sha512-b7AEhSf6CvZgvuDcWMFDeKx2mQSn9AVnMQVyxNxFeHCtLz3gJicqCOlw2GOXM8HKh6PInLdil/NVCDcstwSrIw==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.5 + timsort: 0.3.0 + z-schema: 3.18.4 + dev: true + + /@rushstack/node-core-library/3.44.1: + resolution: {integrity: sha512-qK2BKuRoy6Vh83qjXxilafsUJ1soXzEX0rtkxmAC+GsKOdEVav74Df5859bvY2Ap0JNnYfGfXukX/8o3vqODyw==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.5 + timsort: 0.3.0 + z-schema: 3.18.4 + dev: false + + /@rushstack/node-core-library/3.44.2: + resolution: {integrity: sha512-lQ8Ct267UKkNSJSDxpBWn7SyyITWQ9l3Xqww0V+YY0rMt02r9eiGvwwPaU1ugJW7IMVo6r/HXvgbmpOSPyzGyg==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.5 + timsort: 0.3.0 + z-schema: 5.0.2 + dev: true + + /@rushstack/node-core-library/3.45.0: + resolution: {integrity: sha512-YMuIJl19vQT1+g/OU9mLY6T5ZBT9uDlmeXExDQACpGuxTJW+LHNbk/lRX+eCApQI2eLBlaL4U68r3kZlqwbdmw==} + dependencies: + '@types/node': 12.20.24 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.17.0 + semver: 7.3.5 + timsort: 0.3.0 + z-schema: 5.0.2 + dev: false + + /@rushstack/rig-package/0.3.5: + resolution: {integrity: sha512-CvqWw+E81U5lRBN/lUj7Ngr/XQa/PPb2jAS5QcLP7WL+IMUl+3+Cc2qYrsDoB4zke81kz+usWGmBQpBzGMLmAA==} + dependencies: + resolve: 1.17.0 + strip-json-comments: 3.1.1 + dev: true + + /@rushstack/rig-package/0.3.6: + resolution: {integrity: sha512-H/uFsAT6cD4JCYrlQXYMZg+wPVECByFoJLGqfGRiTwSS5ngQw9QxnFV2mPG2LrxFUsMjLQ2lsrYr523700XzfA==} + dependencies: + resolve: 1.17.0 + strip-json-comments: 3.1.1 + dev: true + + /@rushstack/rush-sdk/5.62.4: + resolution: {integrity: sha512-4dBir//6Vk260DMYNg8g/F8SDa/O5KkoQBGAnz3rleyD8mWt448cRaQvyGSScvXngLkDtsxFMb1bIBpIjOx0Ww==} + dependencies: + '@rushstack/node-core-library': 3.45.0 + '@types/node-fetch': 1.6.9 + tapable: 2.2.1 + dev: false + + /@rushstack/tree-pattern/0.2.2: + resolution: {integrity: sha512-0KdqI7hGtVIlxobOBLWet0WGiD70V/QoYQr5A2ikACeQmIaN4WT6Fn9BcvgwgaSIMcazEcD8ql7Fb9N4dKdQlA==} + dev: true + + /@rushstack/ts-command-line/4.10.4: + resolution: {integrity: sha512-4T5ao4UgDb6LmiRj4GumvG3VT/p6RSMgl7TN7S58ifaAGN2GeTNBajFCDdJs9QQP0d/4tA5p0SFzT7Ps5Byirg==} + dependencies: + '@types/argparse': 1.0.38 + argparse: 1.0.10 + colors: 1.2.5 + string-argv: 0.3.1 + dev: true + + /@rushstack/ts-command-line/4.10.5: + resolution: {integrity: sha512-5fVlTDbKsJ5WyT6L7NrnOlLG3uoITKxoqTPP2j0QZEi95kPbVT4+VPZaXXDJtkrao9qrIyig8pLK9WABY1bb3w==} + dependencies: + '@types/argparse': 1.0.38 + argparse: 1.0.10 + colors: 1.2.5 + string-argv: 0.3.1 + dev: true + + /@sinonjs/commons/1.8.3: + resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@tootallnate/once/1.1.2: + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + dev: false + + /@tsconfig/node10/1.0.8: + resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} + dev: false + + /@tsconfig/node12/1.0.9: + resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} + dev: false + + /@tsconfig/node14/1.0.1: + resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} + dev: false + + /@tsconfig/node16/1.0.2: + resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} + dev: false + + /@types/argparse/1.0.38: + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + dev: true + + /@types/babel__core/7.1.17: + resolution: {integrity: sha512-6zzkezS9QEIL8yCBvXWxPTJPNuMeECJVxSOhxNY/jfq9LxOTHivaYTqr37n9LknWWRTIkzqH2UilS5QFvfa90A==} + dependencies: + '@babel/parser': 7.16.4 + '@babel/types': 7.16.0 + '@types/babel__generator': 7.6.3 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.14.2 + dev: true + + /@types/babel__generator/7.6.3: + resolution: {integrity: sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@types/babel__template/7.4.1: + resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + dependencies: + '@babel/parser': 7.16.4 + '@babel/types': 7.16.0 + dev: true + + /@types/babel__traverse/7.14.2: + resolution: {integrity: sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==} + dependencies: + '@babel/types': 7.16.0 + dev: true + + /@types/blessed/0.1.19: + resolution: {integrity: sha512-r4qnseYWBsi/kxo5AAlCS22EnTXFbGpnvuXUubJikVeRnYB3e5HwV3NtcwJ0Sk5KOGaLvo9Rtwb8hzxfbqbQPg==} + dependencies: + '@types/node': 12.20.24 + dev: true + + /@types/ejs/3.1.1: + resolution: {integrity: sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==} + dev: true + + /@types/fs-extra/9.0.13: + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + dependencies: + '@types/node': 12.20.24 + dev: true + + /@types/glob/7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 12.20.24 + dev: false + + /@types/graceful-fs/4.1.5: + resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} + dependencies: + '@types/node': 12.20.24 + dev: true + + /@types/heft-jest/1.0.1: + resolution: {integrity: sha512-cF2iEUpvGh2WgLowHVAdjI05xuDo+GwCA8hGV3Q5PBl8apjd6BTcpPFQ2uPlfUM7BLpgur2xpYo8VeBXopMI4A==} + dependencies: + '@types/jest': 27.0.3 + dev: true + + /@types/inquirer-autocomplete-prompt/3.0.0: + resolution: {integrity: sha512-qgaINEdGNMP4fq3BJi5rvs8iMNrYhrp6krGwuVJ3jhFr+6gwqiHPSWrKov4x9vCJFbpzDVoDYjNdFG3kepdhDw==} + dependencies: + '@types/inquirer': 8.1.3 + dev: false + + /@types/inquirer/6.5.0: + resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} + dependencies: + '@types/through': 0.0.30 + rxjs: 6.6.7 + dev: false + + /@types/inquirer/8.1.3: + resolution: {integrity: sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==} + dependencies: + '@types/through': 0.0.30 + rxjs: 7.4.0 + + /@types/istanbul-lib-coverage/2.0.3: + resolution: {integrity: sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==} + dev: true + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + dev: true + + /@types/istanbul-reports/1.1.2: + resolution: {integrity: sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/jest/27.0.3: + resolution: {integrity: sha512-cmmwv9t7gBYt7hNKH5Spu7Kuu/DotGa+Ff+JGRKZ4db5eh8PnKS4LuebJ3YLUoyOyIHraTGyULn23YtEAm0VSg==} + dependencies: + jest-diff: 27.4.2 + pretty-format: 27.4.2 + dev: true + + /@types/json-schema/7.0.9: + resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} + dev: true + + /@types/json2md/1.5.1: + resolution: {integrity: sha512-nl3qRDdBUtGeHEhwSeYMtXw5i6UXspS6pxaahmcrE4Fxt0UAvKvsJzu6UMtJ85+yTYiB9nA0TB1kFMEVkYDgUg==} + dev: true + + /@types/lodash/4.14.184: + resolution: {integrity: sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==} + dev: true + + /@types/minimatch/5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + /@types/minipass/3.1.0: + resolution: {integrity: sha512-b2yPKwCrB8x9SB65kcCistMoe3wrYnxxt5rJSZ1kprw0uOXvhuKi9kTQ746Y+Pbqoh+9C0N4zt0ztmTnG9yg7A==} + dependencies: + '@types/node': 12.20.24 + dev: true + + /@types/node-fetch/1.6.9: + resolution: {integrity: sha512-n2r6WLoY7+uuPT7pnEtKJCmPUGyJ+cbyBR8Avnu4+m1nzz7DwBVuyIvvlBzCZ/nrpC7rIgb3D6pNavL7rFEa9g==} + dependencies: + '@types/node': 12.20.24 + dev: false + + /@types/node-fetch/2.5.12: + resolution: {integrity: sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==} + dependencies: + '@types/node': 12.20.24 + form-data: 3.0.1 + dev: true + + /@types/node/12.20.24: + resolution: {integrity: sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==} + + /@types/normalize-package-data/2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /@types/npm-package-arg/6.1.1: + resolution: {integrity: sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==} + dev: true + + /@types/npm-registry-fetch/8.0.2: + resolution: {integrity: sha512-ps8VPCldQJhWXKrM4FYv+X5e2CGTKciHcCFAS+QTjEuP5JX9K6BZ2q/YF/vv7wy+krfJmHbDj0l6AwDcjRIeHA==} + dependencies: + '@types/node': 12.20.24 + '@types/node-fetch': 2.5.12 + '@types/npm-package-arg': 6.1.1 + '@types/npmlog': 4.1.3 + '@types/ssri': 7.1.1 + dev: true + + /@types/npmlog/4.1.3: + resolution: {integrity: sha512-1TcL7YDYCtnHmLhTWbum+IIwLlvpaHoEKS2KNIngEwLzwgDeHaebaEHHbQp8IqzNQ9IYiboLKUjAf7MZqG63+w==} + dev: true + + /@types/pacote/11.1.1: + resolution: {integrity: sha512-ycBhPpDuNb5hwvWQJFaLyGspdWXkpqBOcGyWclC+hQfMvZt/13aXIt5vx5b+wx4lJd8n0ROZEPMCt6C9uGP0ag==} + dependencies: + '@types/node': 12.20.24 + '@types/npm-registry-fetch': 8.0.2 + '@types/npmlog': 4.1.3 + '@types/ssri': 7.1.1 + dev: true + + /@types/prettier/1.19.1: + resolution: {integrity: sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==} + dev: true + + /@types/ssri/7.1.1: + resolution: {integrity: sha512-DPP/jkDaqGiyU75MyMURxLWyYLwKSjnAuGe9ZCsLp9QZOpXmDfuevk769F0BS86TmRuD5krnp06qw9nSoNO+0g==} + dependencies: + '@types/node': 12.20.24 + dev: true + + /@types/stack-utils/1.0.1: + resolution: {integrity: sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==} + dev: true + + /@types/tapable/1.0.6: + resolution: {integrity: sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==} + dev: true + + /@types/tar/6.1.1: + resolution: {integrity: sha512-8mto3YZfVpqB1CHMaYz1TUYIQfZFbh/QbEq5Hsn6D0ilCfqRVCdalmc89B7vi3jhl9UYIk+dWDABShNfOkv5HA==} + dependencies: + '@types/minipass': 3.1.0 + '@types/node': 12.20.24 + dev: true + + /@types/through/0.0.30: + resolution: {integrity: sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==} + dependencies: + '@types/node': 12.20.24 + + /@types/yargs-parser/20.2.1: + resolution: {integrity: sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==} + dev: true + + /@types/yargs/15.0.14: + resolution: {integrity: sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==} + dependencies: + '@types/yargs-parser': 20.2.1 + dev: true + + /@types/yargs/16.0.4: + resolution: {integrity: sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==} + dependencies: + '@types/yargs-parser': 20.2.1 + dev: true + + /@types/yargs/17.0.7: + resolution: {integrity: sha512-OvLKmpKdea1aWtqHv9bxVVcMoT6syAeK+198dfETIFkAevYRGwqh4H+KFxfjUETZuUuE5sQCAFwdOdoHUdo8eg==} + dependencies: + '@types/yargs-parser': 20.2.1 + dev: true + + /@typescript-eslint/eslint-plugin/4.31.2_326168addec61fdd42b406abb1a8f069: + resolution: {integrity: sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + '@typescript-eslint/parser': ^4.0.0 + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.2 + '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.2 + '@typescript-eslint/scope-manager': 4.31.2 + debug: 4.3.3 + eslint: 7.32.0 + functional-red-black-tree: 1.0.1 + regexpp: 3.2.0 + semver: 7.3.5 + tsutils: 3.21.0_typescript@4.4.2 + typescript: 4.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/experimental-utils/4.31.2_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: '*' + dependencies: + '@types/json-schema': 7.0.9 + '@typescript-eslint/scope-manager': 4.31.2 + '@typescript-eslint/types': 4.31.2 + '@typescript-eslint/typescript-estree': 4.31.2_typescript@4.4.2 + eslint: 7.32.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/parser/4.31.2_eslint@7.32.0+typescript@4.4.2: + resolution: {integrity: sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 4.31.2 + '@typescript-eslint/types': 4.31.2 + '@typescript-eslint/typescript-estree': 4.31.2_typescript@4.4.2 + debug: 4.3.3 + eslint: 7.32.0 + typescript: 4.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager/4.31.2: + resolution: {integrity: sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dependencies: + '@typescript-eslint/types': 4.31.2 + '@typescript-eslint/visitor-keys': 4.31.2 + dev: true + + /@typescript-eslint/types/4.31.2: + resolution: {integrity: sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dev: true + + /@typescript-eslint/typescript-estree/4.31.2_typescript@4.4.2: + resolution: {integrity: sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 4.31.2 + '@typescript-eslint/visitor-keys': 4.31.2 + debug: 4.3.3 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.5 + tsutils: 3.21.0_typescript@4.4.2 + typescript: 4.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/visitor-keys/4.31.2: + resolution: {integrity: sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dependencies: + '@typescript-eslint/types': 4.31.2 + eslint-visitor-keys: 2.1.0 + dev: true + + /abab/2.0.5: + resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==} + dev: true + + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + + /acorn-globals/4.3.4: + resolution: {integrity: sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==} + dependencies: + acorn: 6.4.2 + acorn-walk: 6.2.0 + dev: true + + /acorn-jsx/5.3.2_acorn@7.4.1: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 7.4.1 + dev: true + + /acorn-walk/6.2.0: + resolution: {integrity: sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: false + + /acorn/6.4.2: + resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /acorn/7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /acorn/8.6.0: + resolution: {integrity: sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.3 + transitivePeerDependencies: + - supports-color + dev: false + + /agentkeepalive/4.1.4: + resolution: {integrity: sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 4.3.3 + depd: 1.1.2 + humanize-ms: 1.2.1 + transitivePeerDependencies: + - supports-color + dev: false + + /aggregate-error/3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv/8.8.2: + resolution: {integrity: sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-bgblack/0.1.1: + resolution: {integrity: sha1-poulAHiHcBtqr74/oNrf36juPKI=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgblue/0.1.1: + resolution: {integrity: sha1-Z73ATtybm1J4lp2hlt6j11yMNhM=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgcyan/0.1.1: + resolution: {integrity: sha1-WEiUJWAL3p9VBwaN2Wnr/bUP52g=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bggreen/0.1.1: + resolution: {integrity: sha1-TjGRJIUplD9DIelr8THRwTgWr0k=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgmagenta/0.1.1: + resolution: {integrity: sha1-myhDLAduqpmUGGcqPvvhk5HCx6E=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgred/0.1.1: + resolution: {integrity: sha1-p2+Sg4OCukMpCmwXeEJPmE1vEEE=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgwhite/0.1.1: + resolution: {integrity: sha1-ZQRlE3elim7OzQMxmU5IAljhG6g=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bgyellow/0.1.1: + resolution: {integrity: sha1-w/4usIzUdmSAKeaHTRWgs49h1E8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-black/0.1.1: + resolution: {integrity: sha1-9hheiJNgslRaHsUMC/Bj/EMDJFM=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-blue/0.1.1: + resolution: {integrity: sha1-FbgEmQ6S/JyoxUds6PaZd3wh7b8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-bold/0.1.1: + resolution: {integrity: sha1-PmOVCvWswq4uZw5vZ96xFdGl9QU=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-colors/0.2.0: + resolution: {integrity: sha1-csMd4qDZoszQysMMyYI+6y9kNLU=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-bgblack: 0.1.1 + ansi-bgblue: 0.1.1 + ansi-bgcyan: 0.1.1 + ansi-bggreen: 0.1.1 + ansi-bgmagenta: 0.1.1 + ansi-bgred: 0.1.1 + ansi-bgwhite: 0.1.1 + ansi-bgyellow: 0.1.1 + ansi-black: 0.1.1 + ansi-blue: 0.1.1 + ansi-bold: 0.1.1 + ansi-cyan: 0.1.1 + ansi-dim: 0.1.1 + ansi-gray: 0.1.1 + ansi-green: 0.1.1 + ansi-grey: 0.1.1 + ansi-hidden: 0.1.1 + ansi-inverse: 0.1.1 + ansi-italic: 0.1.1 + ansi-magenta: 0.1.1 + ansi-red: 0.1.1 + ansi-reset: 0.1.1 + ansi-strikethrough: 0.1.1 + ansi-underline: 0.1.1 + ansi-white: 0.1.1 + ansi-yellow: 0.1.1 + lazy-cache: 2.0.2 + dev: false + + /ansi-colors/4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + + /ansi-cyan/0.1.1: + resolution: {integrity: sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-dim/0.1.1: + resolution: {integrity: sha1-QN5MYDqoCG2Oeoa4/5mNXDbu/Ww=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + + /ansi-escapes/5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 + dev: false + + /ansi-gray/0.1.1: + resolution: {integrity: sha1-KWLPVOyXksSFEKPetSRDaGHvclE=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-green/0.1.1: + resolution: {integrity: sha1-il2al55FjVfEDjNYCzc5C44Q0Pc=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-grey/0.1.1: + resolution: {integrity: sha1-WdmLasK6GfilF5jphT+6eDOaM8E=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-hidden/0.1.1: + resolution: {integrity: sha1-7WpMSY0rt8uyidvyqNHcyFZ/rg8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-inverse/0.1.1: + resolution: {integrity: sha1-tq9Fgm/oJr+1KKbHmIV5Q1XM0mk=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-italic/0.1.1: + resolution: {integrity: sha1-EEdDRj9iXBQqA2c5z4XtpoiYbyM=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-magenta/0.1.1: + resolution: {integrity: sha1-BjtboW+z8j4c/aKwfAqJ3hHkMK4=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-red/0.1.1: + resolution: {integrity: sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-regex/2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: false + + /ansi-regex/4.1.0: + resolution: {integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==} + engines: {node: '>=6'} + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-reset/0.1.1: + resolution: {integrity: sha1-5+cSksPH3c1NYu9KbHwFmAkRw7c=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-strikethrough/0.1.1: + resolution: {integrity: sha1-2Eh3FAss/wfRyT685pkE9oiF5Wg=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-styles/2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: false + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles/6.1.0: + resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==} + engines: {node: '>=12'} + dev: false + + /ansi-term/0.0.2: + resolution: {integrity: sha512-jLnGE+n8uAjksTJxiWZf/kcUmXq+cRWSl550B9NmQ8YiqaTM+lILcSe5dHdp8QkJPhaOghDjnMKwyYSMjosgAA==} + dependencies: + x256: 0.0.2 + dev: false + + /ansi-underline/0.1.1: + resolution: {integrity: sha1-38kg9Ml7WXfqFi34/7mIMIqqcaQ=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-white/0.1.1: + resolution: {integrity: sha1-nHe3wZPF7pkuYBHTbsTJIbRXiUQ=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansi-wrap/0.1.0: + resolution: {integrity: sha1-qCJQ3bABXponyoLoLqYDu/pF768=} + engines: {node: '>=0.10.0'} + dev: false + + /ansi-yellow/0.1.1: + resolution: {integrity: sha1-y5NW8vRscy8OMZnmEClVp32oPB0=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-wrap: 0.1.0 + dev: false + + /ansicolors/0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + dev: false + + /anymatch/2.0.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + dependencies: + micromatch: 3.1.10 + normalize-path: 2.1.1 + dev: true + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.0 + dev: true + + /aproba/2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /are-we-there-yet/2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + dev: false + + /arg/4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: false + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + + /arr-diff/4.0.0: + resolution: {integrity: sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=} + engines: {node: '>=0.10.0'} + + /arr-flatten/1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + + /arr-union/3.1.0: + resolution: {integrity: sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=} + engines: {node: '>=0.10.0'} + + /array-equal/1.0.0: + resolution: {integrity: sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=} + dev: true + + /array-includes/3.1.4: + resolution: {integrity: sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + get-intrinsic: 1.1.1 + is-string: 1.0.7 + dev: true + + /array-sort/0.1.4: + resolution: {integrity: sha512-BNcM+RXxndPxiZ2rd76k6nyQLRZr2/B/sdi8pQ+Joafr5AH279L40dfokSUTp8O+AaqYjXWhblBWa2st2nc4fQ==} + engines: {node: '>=0.10.0'} + dependencies: + default-compare: 1.0.0 + get-value: 2.0.6 + kind-of: 5.1.0 + dev: false + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + /array-unique/0.3.2: + resolution: {integrity: sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=} + engines: {node: '>=0.10.0'} + + /array.prototype.flatmap/1.2.5: + resolution: {integrity: sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + dev: true + + /asn1/0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /assert-plus/1.0.0: + resolution: {integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=} + engines: {node: '>=0.8'} + dev: true + + /assign-symbols/1.0.0: + resolution: {integrity: sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=} + engines: {node: '>=0.10.0'} + + /astral-regex/1.0.0: + resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} + engines: {node: '>=4'} + dev: true + + /astral-regex/2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + /async/3.2.4: + resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} + dev: true + + /asynckit/0.4.0: + resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=} + dev: true + + /atob/2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + /autolinker/0.28.1: + resolution: {integrity: sha1-BlK0kYgYefB3XazgzcoyM5QqTkc=} + dependencies: + gulp-header: 1.8.12 + dev: false + + /aws-sign2/0.7.0: + resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=} + dev: true + + /aws4/1.11.0: + resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==} + dev: true + + /babel-jest/25.5.1_@babel+core@7.16.0: + resolution: {integrity: sha512-9dA9+GmMjIzgPnYtkhBg73gOo/RHqPmLruP3BaGL4KEX3Dwz6pI8auSN8G8+iuEG90+GSswyKvslN+JYSaacaQ==} + engines: {node: '>= 8.3'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.0 + '@jest/transform': 25.5.1 + '@jest/types': 25.5.0 + '@types/babel__core': 7.1.17 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 25.5.0_@babel+core@7.16.0 + chalk: 3.0.0 + graceful-fs: 4.2.8 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul/6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.14.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.1.0 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist/25.5.0: + resolution: {integrity: sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/template': 7.16.0 + '@babel/types': 7.16.0 + '@types/babel__traverse': 7.14.2 + dev: true + + /babel-preset-current-node-syntax/0.1.4_@babel+core@7.16.0: + resolution: {integrity: sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.0 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.0 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.16.0 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.16.0 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.0 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.0 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.0 + dev: true + + /babel-preset-jest/25.5.0_@babel+core@7.16.0: + resolution: {integrity: sha512-8ZczygctQkBU+63DtSOKGh7tFL0CeCuz+1ieud9lJ1WPQ9O6A1a/r+LGn6Y705PA6whHQ3T1XuB/PmpfNYf8Fw==} + engines: {node: '>= 8.3'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.0 + babel-plugin-jest-hoist: 25.5.0 + babel-preset-current-node-syntax: 0.1.4_@babel+core@7.16.0 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base/0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.0 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /bcrypt-pbkdf/1.0.2: + resolution: {integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=} + dependencies: + tweetnacl: 0.14.5 + dev: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: false + + /blessed-contrib/4.11.0: + resolution: {integrity: sha512-P00Xji3xPp53+FdU9f74WpvnOAn/SS0CKLy4vLAf5Ps7FGDOTY711ruJPZb3/7dpFuP+4i7f4a/ZTZdLlKG9WA==} + dependencies: + ansi-term: 0.0.2 + chalk: 1.1.3 + drawille-canvas-blessed-contrib: 0.1.3 + lodash: 4.17.21 + map-canvas: 0.1.5 + marked: 4.2.12 + marked-terminal: 5.1.1_marked@4.2.12 + memory-streams: 0.1.3 + memorystream: 0.3.1 + picture-tuber: 1.0.2 + sparkline: 0.1.2 + strip-ansi: 3.0.1 + term-canvas: 0.0.5 + x256: 0.0.2 + dev: false + + /blessed/0.1.81: + resolution: {integrity: sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==} + engines: {node: '>= 0.8.0'} + hasBin: true + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + + /braces/2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + + /bresenham/0.0.3: + resolution: {integrity: sha512-wbMxoJJM1p3+6G7xEFXYNCJ30h2qkwmVxebkbwIl4OcnWtno5R3UT9VuYLfStlVNAQCmRjkGwjPFdfaPd4iNXw==} + dev: false + + /browser-process-hrtime/1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + dev: true + + /browser-resolve/1.11.3: + resolution: {integrity: sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==} + dependencies: + resolve: 1.1.7 + dev: true + + /browserslist/4.18.1: + resolution: {integrity: sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001286 + electron-to-chromium: 1.4.14 + escalade: 3.1.1 + node-releases: 2.0.1 + picocolors: 1.0.0 + dev: true + + /bser/2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /buffers/0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + dev: false + + /builtins/1.0.3: + resolution: {integrity: sha1-y5T662HIaWRR2zZTThQi+U8K7og=} + dev: false + + /cacache/15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + dependencies: + '@npmcli/fs': 1.0.0 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.0 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.1.5 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.1.11 + unique-filename: 1.1.1 + dev: false + + /cache-base/1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.0 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.1 + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camel-case/3.0.0: + resolution: {integrity: sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite/1.0.30001286: + resolution: {integrity: sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==} + dev: true + + /capture-exit/2.0.0: + resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} + engines: {node: 6.* || 8.* || >= 10.*} + dependencies: + rsvp: 4.8.5 + dev: true + + /cardinal/2.1.1: + resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} + hasBin: true + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + dev: false + + /caseless/0.12.0: + resolution: {integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=} + dev: true + + /chalk/1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: false + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk/5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /change-case/3.1.0: + resolution: {integrity: sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==} + dependencies: + camel-case: 3.0.0 + constant-case: 2.0.0 + dot-case: 2.1.1 + header-case: 1.0.1 + is-lower-case: 1.1.3 + is-upper-case: 1.1.2 + lower-case: 1.1.4 + lower-case-first: 1.0.2 + no-case: 2.3.2 + param-case: 2.1.1 + pascal-case: 2.0.1 + path-case: 2.1.1 + sentence-case: 2.1.1 + snake-case: 2.1.0 + swap-case: 1.1.2 + title-case: 2.1.1 + upper-case: 1.1.3 + upper-case-first: 1.1.2 + dev: false + + /chardet/0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: false + + /charm/0.1.2: + resolution: {integrity: sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==} + dev: false + + /chokidar/3.4.3: + resolution: {integrity: sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.5.0 + optionalDependencies: + fsevents: 2.1.3 + dev: true + + /chownr/2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + + /ci-info/2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + dev: true + + /class-utils/0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + /clean-stack/2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + /cli-cursor/3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: false + + /cli-spinners/2.6.1: + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} + dev: false + + /cli-table3/0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: false + + /cli-truncate/2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: false + + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.0 + dev: false + + /cli-width/3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: false + + /cliui/6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /cliui/7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /clone/1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: false + + /co/4.6.0: + resolution: {integrity: sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage/1.0.1: + resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} + dev: true + + /collection-visit/1.0.0: + resolution: {integrity: sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /color-support/1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + + /colorette/2.0.16: + resolution: {integrity: sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==} + dev: false + + /colors/1.2.5: + resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} + engines: {node: '>=0.1.90'} + + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander/2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + requiresBuild: true + optional: true + + /commander/8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /commander/9.4.0: + resolution: {integrity: sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==} + engines: {node: ^12.20.0 || >=14} + dev: false + + /component-emitter/1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /concat-with-sourcemaps/1.1.0: + resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + dependencies: + source-map: 0.6.1 + dev: false + + /console-control-strings/1.1.0: + resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} + dev: false + + /constant-case/2.0.0: + resolution: {integrity: sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=} + dependencies: + snake-case: 2.1.0 + upper-case: 1.1.3 + dev: false + + /convert-source-map/1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /copy-descriptor/0.1.1: + resolution: {integrity: sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=} + engines: {node: '>=0.10.0'} + + /core-js-pure/3.20.1: + resolution: {integrity: sha512-yeNNr3L9cEBwNy6vhhIJ0nko7fE7uFO6PgawcacGt2VWep4WqQx0RiqlkgSP7kqUMC1IKdfO9qPeWXcUheHLVQ==} + requiresBuild: true + dev: false + + /core-util-is/1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + + /create-frame/1.0.0: + resolution: {integrity: sha1-i5XyaR4ySbYIBEPjPQutn49pdao=} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + extend-shallow: 2.0.1 + isobject: 3.0.1 + lazy-cache: 2.0.2 + dev: false + + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: false + + /cross-spawn/6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /cssom/0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + dev: true + + /cssom/0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + dev: true + + /cssstyle/2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + dependencies: + cssom: 0.3.8 + dev: true + + /dashdash/1.14.1: + resolution: {integrity: sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + + /data-urls/1.1.0: + resolution: {integrity: sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==} + dependencies: + abab: 2.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 7.1.0 + dev: true + + /date.js/0.3.3: + resolution: {integrity: sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==} + dependencies: + debug: 3.1.0 + dev: false + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + dependencies: + ms: 2.0.0 + + /debug/3.1.0: + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + dependencies: + ms: 2.0.0 + dev: false + + /debug/4.3.3: + resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /debug/4.3.3_supports-color@9.2.1: + resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 9.2.1 + dev: false + + /decamelize/1.2.0: + resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} + engines: {node: '>=0.10.0'} + dev: true + + /decode-uri-component/0.2.0: + resolution: {integrity: sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=} + engines: {node: '>=0.10'} + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: true + + /default-compare/1.0.0: + resolution: {integrity: sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 5.1.0 + dev: false + + /defaults/1.0.3: + resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} + dependencies: + clone: 1.0.4 + dev: false + + /define-properties/1.1.3: + resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} + engines: {node: '>= 0.4'} + dependencies: + object-keys: 1.1.1 + dev: true + + /define-property/0.2.5: + resolution: {integrity: sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.6 + + /define-property/1.0.0: + resolution: {integrity: sha1-dp66rz9KY6rTr56NMEybvnm/sOY=} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + + /define-property/2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + isobject: 3.0.1 + + /del/5.1.0: + resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} + engines: {node: '>=8'} + dependencies: + globby: 10.0.2 + graceful-fs: 4.2.8 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 3.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + dev: false + + /del/6.1.1: + resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} + engines: {node: '>=10'} + dependencies: + globby: 11.1.0 + graceful-fs: 4.2.8 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 4.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + dev: true + + /delayed-stream/1.0.0: + resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=} + engines: {node: '>=0.4.0'} + dev: true + + /delegates/1.0.0: + resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} + dev: false + + /depd/1.1.2: + resolution: {integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=} + engines: {node: '>= 0.6'} + dev: false + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: false + + /detect-newline/3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + /diff-sequences/25.2.6: + resolution: {integrity: sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==} + engines: {node: '>= 8.3'} + dev: true + + /diff-sequences/27.4.0: + resolution: {integrity: sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: false + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + + /doctrine/2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /domexception/1.0.1: + resolution: {integrity: sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==} + dependencies: + webidl-conversions: 4.0.2 + dev: true + + /dot-case/2.1.1: + resolution: {integrity: sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=} + dependencies: + no-case: 2.3.2 + dev: false + + /drawille-blessed-contrib/1.0.0: + resolution: {integrity: sha512-WnHMgf5en/hVOsFhxLI8ZX0qTJmerOsVjIMQmn4cR1eI8nLGu+L7w5ENbul+lZ6w827A3JakCuernES5xbHLzQ==} + dev: false + + /drawille-canvas-blessed-contrib/0.1.3: + resolution: {integrity: sha512-bdDvVJOxlrEoPLifGDPaxIzFh3cD7QH05ePoQ4fwnqfi08ZSxzEhOUpI5Z0/SQMlWgcCQOEtuw0zrwezacXglw==} + dependencies: + ansi-term: 0.0.2 + bresenham: 0.0.3 + drawille-blessed-contrib: 1.0.0 + gl-matrix: 2.8.1 + x256: 0.0.2 + dev: false + + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /ecc-jsbn/0.1.2: + resolution: {integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: true + + /ejs/3.1.8: + resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.8.5 + dev: true + + /electron-to-chromium/1.4.14: + resolution: {integrity: sha512-RsGkAN9JEAYMObS72kzUsPPcPGMqX1rBqGuXi9aa4TBKLzICoLf+DAAtd0fVFzrniJqYzpby47gthCUoObfs0Q==} + dev: true + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /encoding/0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true + dependencies: + iconv-lite: 0.6.3 + dev: false + optional: true + + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + + /enquirer/2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.1 + dev: true + + /ent/2.2.0: + resolution: {integrity: sha1-6WQhkyWiHQX0RGai9obtbOX13R0=} + dev: false + + /env-paths/2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: false + + /err-code/2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + dev: false + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /error-symbol/0.1.0: + resolution: {integrity: sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y=} + engines: {node: '>=0.10.0'} + dev: false + + /es-abstract/1.19.1: + resolution: {integrity: sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + get-intrinsic: 1.1.1 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-symbols: 1.0.2 + internal-slot: 1.0.3 + is-callable: 1.2.4 + is-negative-zero: 2.0.1 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.1 + is-string: 1.0.7 + is-weakref: 1.0.1 + object-inspect: 1.12.0 + object-keys: 1.1.1 + object.assign: 4.1.2 + string.prototype.trimend: 1.0.4 + string.prototype.trimstart: 1.0.4 + unbox-primitive: 1.0.1 + dev: true + + /es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.4 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escodegen/1.14.3: + resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} + engines: {node: '>=4.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 4.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + + /eslint-plugin-promise/4.2.1: + resolution: {integrity: sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==} + engines: {node: '>=6'} + dev: true + + /eslint-plugin-react/7.20.6_eslint@7.32.0: + resolution: {integrity: sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 + dependencies: + array-includes: 3.1.4 + array.prototype.flatmap: 1.2.5 + doctrine: 2.1.0 + eslint: 7.32.0 + has: 1.0.3 + jsx-ast-utils: 2.4.1 + object.entries: 1.1.5 + object.fromentries: 2.0.5 + object.values: 1.1.5 + prop-types: 15.7.2 + resolve: 1.20.0 + string.prototype.matchall: 4.0.6 + dev: true + + /eslint-plugin-tsdoc/0.2.14: + resolution: {integrity: sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==} + dependencies: + '@microsoft/tsdoc': 0.13.2 + '@microsoft/tsdoc-config': 0.15.2 + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-utils/3.0.0_eslint@7.32.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 7.32.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint/7.30.0: + resolution: {integrity: sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==} + engines: {node: ^10.12.0 || >=12.0.0} + hasBin: true + dependencies: + '@babel/code-frame': 7.12.11 + '@eslint/eslintrc': 0.4.3 + '@humanwhocodes/config-array': 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.3 + doctrine: 3.0.0 + enquirer: 2.3.6 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.12.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.0.4 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.3.5 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + table: 6.7.5 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint/7.32.0: + resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} + engines: {node: ^10.12.0 || >=12.0.0} + hasBin: true + dependencies: + '@babel/code-frame': 7.12.11 + '@eslint/eslintrc': 0.4.3 + '@humanwhocodes/config-array': 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.3 + doctrine: 3.0.0 + enquirer: 2.3.6 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.12.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.0.4 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.3.5 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + table: 6.7.5 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/7.3.1: + resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.2_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + dev: true + + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + /esquery/1.4.0: + resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /event-stream/0.9.8: + resolution: {integrity: sha512-o5h0Mp1bkoR6B0i7pTCAzRy+VzdsRWH997KQD4Psb0EOPoKEIiaRx/EsOdUl7p1Ktjw7aIWvweI/OY1R9XrlUg==} + dependencies: + optimist: 0.2.8 + dev: false + + /exec-sh/0.3.6: + resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} + dev: true + + /execa/1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + dependencies: + cross-spawn: 6.0.5 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.6 + strip-eof: 1.0.0 + dev: true + + /execa/3.4.0: + resolution: {integrity: sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==} + engines: {node: ^8.12.0 || >=9.7.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + p-finally: 2.0.1 + signal-exit: 3.0.6 + strip-final-newline: 2.0.0 + dev: true + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.6 + strip-final-newline: 2.0.0 + dev: false + + /exit/0.1.2: + resolution: {integrity: sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=} + engines: {node: '>= 0.8.0'} + dev: true + + /expand-brackets/2.1.4: + resolution: {integrity: sha1-t3c14xXOMPa27/D4OwQVGiJEliI=} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + + /expect/25.5.0: + resolution: {integrity: sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + ansi-styles: 4.3.0 + jest-get-type: 25.2.6 + jest-matcher-utils: 25.5.0 + jest-message-util: 25.5.0 + jest-regex-util: 25.2.6 + dev: true + + /extend-shallow/2.0.1: + resolution: {integrity: sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + + /extend-shallow/3.0.2: + resolution: {integrity: sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + /extend/3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /external-editor/3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + + /extglob/2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + + /extsprintf/1.3.0: + resolution: {integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=} + engines: {'0': node >=0.6.0} + dev: true + + /falsey/0.3.2: + resolution: {integrity: sha512-lxEuefF5MBIVDmE6XeqCdM4BWk1+vYmGZtkbKZ/VFcg6uBBw6fXNEbWmxCjDdQlFc9hy450nkiWwM3VAW6G1qg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 5.1.0 + dev: false + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob/3.2.11: + resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: true + + /fast-glob/3.2.7: + resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} + engines: {node: '>=8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: false + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + + /fb-watchman/2.0.1: + resolution: {integrity: sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==} + dependencies: + bser: 2.1.1 + dev: true + + /figures/3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: false + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /filelist/1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.1 + dev: true + + /fill-range/4.0.0: + resolution: {integrity: sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: false + + /flat-cache/3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.4 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.4: + resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==} + dev: true + + /for-in/1.0.2: + resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=} + engines: {node: '>=0.10.0'} + + /for-own/1.0.0: + resolution: {integrity: sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + dev: false + + /forever-agent/0.6.1: + resolution: {integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=} + dev: true + + /form-data/2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.34 + dev: true + + /form-data/3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.34 + dev: true + + /fragment-cache/0.2.1: + resolution: {integrity: sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + + /fs-exists-sync/0.1.0: + resolution: {integrity: sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=} + engines: {node: '>=0.10.0'} + dev: false + + /fs-extra/10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.8 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + + /fs-extra/7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.8 + jsonfile: 4.0.0 + universalify: 0.1.2 + + /fs-minipass/2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.5 + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /fsevents/2.1.3: + resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + deprecated: '"Please update to latest v2.3 or v2.2"' + requiresBuild: true + dev: true + optional: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + /functional-red-black-tree/1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + dev: true + + /gauge/4.0.0: + resolution: {integrity: sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + dependencies: + ansi-regex: 5.0.1 + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.6 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + /get-intrinsic/1.1.1: + resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.2 + dev: true + + /get-object/0.2.0: + resolution: {integrity: sha1-2S/31RkMZFMM2gVD2sY6PUf+jAw=} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 2.1.0 + isobject: 0.2.0 + dev: false + + /get-package-type/0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream/4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream/5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.1 + dev: true + + /get-value/2.0.6: + resolution: {integrity: sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=} + engines: {node: '>=0.10.0'} + + /getpass/0.1.7: + resolution: {integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=} + dependencies: + assert-plus: 1.0.0 + dev: true + + /git-hooks-list/1.0.3: + resolution: {integrity: sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==} + dev: false + + /gl-matrix/2.8.1: + resolution: {integrity: sha512-0YCjVpE3pS5XWlN3J4X7AiAx65+nqAI54LndtVFnQZB6G/FVLkZH8y8V6R3cIoOQR4pUdfwQGd1iwyoXHJ4Qfw==} + dev: false + + /glob-escape/0.0.2: + resolution: {integrity: sha512-L/cXYz8x7qer1HAyUQ+mbjcUsJVdpRxpAf7CwqHoNBs9vTpABlGfNN4tzkDxt+u3Z7ZncVyKlCNPtzb0R/7WbA==} + engines: {node: '>= 0.10'} + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob/7.0.6: + resolution: {integrity: sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob/7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals/13.12.0: + resolution: {integrity: sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby/10.0.0: + resolution: {integrity: sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==} + engines: {node: '>=8'} + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.7 + glob: 7.2.0 + ignore: 5.1.9 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /globby/10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.7 + glob: 7.2.0 + ignore: 5.1.9 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.11 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /graceful-fs/4.2.8: + resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + + /growly/1.3.0: + resolution: {integrity: sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=} + dev: true + optional: true + + /gulp-header/1.8.12: + resolution: {integrity: sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==} + deprecated: Removed event-stream from gulp-header + dependencies: + concat-with-sourcemaps: 1.1.0 + lodash.template: 4.5.0 + through2: 2.0.5 + dev: false + + /handlebars-helper-create-frame/0.1.0: + resolution: {integrity: sha1-iqUdEK62QI/MZgXUDXc1YohIegM=} + engines: {node: '>=4'} + dependencies: + create-frame: 1.0.0 + isobject: 3.0.1 + dev: false + + /handlebars-helpers/0.10.0: + resolution: {integrity: sha512-QiyhQz58u/DbuV41VnfpE0nhy6YCH4vB514ajysV8SoKmP+DxU+pR+fahVyNECHj+jiwEN2VrvxD/34/yHaLUg==} + engines: {node: '>=0.12.0'} + dependencies: + arr-flatten: 1.1.0 + array-sort: 0.1.4 + create-frame: 1.0.0 + define-property: 1.0.0 + falsey: 0.3.2 + for-in: 1.0.2 + for-own: 1.0.0 + get-object: 0.2.0 + get-value: 2.0.6 + handlebars: 4.7.7 + handlebars-helper-create-frame: 0.1.0 + handlebars-utils: 1.0.6 + has-value: 1.0.0 + helper-date: 1.0.1 + helper-markdown: 1.0.0 + helper-md: 0.2.2 + html-tag: 2.0.0 + is-even: 1.0.0 + is-glob: 4.0.3 + is-number: 4.0.0 + kind-of: 6.0.3 + lazy-cache: 2.0.2 + logging-helpers: 1.0.0 + micromatch: 3.1.10 + relative: 3.0.2 + striptags: 3.2.0 + to-gfm-code-block: 0.1.1 + year: 0.2.1 + dev: false + + /handlebars-utils/1.0.6: + resolution: {integrity: sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + typeof-article: 0.1.1 + dev: false + + /handlebars/4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.5 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.14.5 + dev: false + + /har-schema/2.0.0: + resolution: {integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=} + engines: {node: '>=4'} + dev: true + + /har-validator/5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + dev: true + + /has-ansi/2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: false + + /has-bigints/1.0.1: + resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-symbols/1.0.2: + resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.2 + dev: true + + /has-unicode/2.0.1: + resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} + dev: false + + /has-value/0.3.1: + resolution: {integrity: sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + /has-value/1.0.0: + resolution: {integrity: sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + /has-values/0.1.4: + resolution: {integrity: sha1-bWHeldkd/Km5oCCJrThL/49it3E=} + engines: {node: '>=0.10.0'} + + /has-values/1.0.0: + resolution: {integrity: sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + + /header-case/1.0.1: + resolution: {integrity: sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /helper-date/1.0.1: + resolution: {integrity: sha512-wU3VOwwTJvGr/w5rZr3cprPHO+hIhlblTJHD6aFBrKLuNbf4lAmkawd2iK3c6NbJEvY7HAmDpqjOFSI5/+Ey2w==} + engines: {node: '>=4.0'} + dependencies: + date.js: 0.3.3 + handlebars-utils: 1.0.6 + moment: 2.29.1 + dev: false + + /helper-markdown/1.0.0: + resolution: {integrity: sha512-AnDqMS4ejkQK0MXze7pA9TM3pu01ZY+XXsES6gEE0RmCGk5/NIfvTn0NmItfyDOjRAzyo9z6X7YHbHX4PzIvOA==} + engines: {node: '>=0.10.0'} + dependencies: + handlebars-utils: 1.0.6 + highlight.js: 9.18.5 + remarkable: 1.7.4 + dev: false + + /helper-md/0.2.2: + resolution: {integrity: sha1-wfWdflW7riM2L9ig6XFgeuxp1B8=} + engines: {node: '>=0.10.0'} + dependencies: + ent: 2.2.0 + extend-shallow: 2.0.1 + fs-exists-sync: 0.1.0 + remarkable: 1.7.4 + dev: false + + /here/0.0.2: + resolution: {integrity: sha512-U7VYImCTcPoY27TSmzoiFsmWLEqQFaYNdpsPb9K0dXJhE6kufUqycaz51oR09CW85dDU9iWyy7At8M+p7hb3NQ==} + dev: false + + /highlight.js/9.18.5: + resolution: {integrity: sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA==} + deprecated: Support has ended for 9.x series. Upgrade to @latest + requiresBuild: true + dev: false + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info/4.0.2: + resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: false + + /html-encoding-sniffer/1.0.2: + resolution: {integrity: sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==} + dependencies: + whatwg-encoding: 1.0.5 + dev: true + + /html-escaper/2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /html-tag/2.0.0: + resolution: {integrity: sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g==} + engines: {node: '>=0.10.0'} + dependencies: + is-self-closing: 1.0.1 + kind-of: 6.0.3 + dev: false + + /http-cache-semantics/4.1.0: + resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} + dev: false + + /http-proxy-agent/4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.3 + transitivePeerDependencies: + - supports-color + dev: false + + /http-signature/1.2.0: + resolution: {integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.16.1 + dev: true + + /https-proxy-agent/5.0.0: + resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.3 + transitivePeerDependencies: + - supports-color + dev: false + + /human-signals/1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: true + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: false + + /humanize-ms/1.2.1: + resolution: {integrity: sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=} + dependencies: + ms: 2.1.2 + dev: false + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /iconv-lite/0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + optional: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore-walk/4.0.1: + resolution: {integrity: sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==} + engines: {node: '>=10'} + dependencies: + minimatch: 3.0.4 + dev: false + + /ignore/4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + dev: true + + /ignore/5.1.9: + resolution: {integrity: sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==} + engines: {node: '>= 4'} + dev: false + + /ignore/5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-lazy/4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + /indento/1.1.13: + resolution: {integrity: sha512-YZWk3mreBEM7sBPddsiQnW9Z8SGg/gNpFfscJq00HCDS7pxcQWWWMSVKJU7YkTRyDu1Zv2s8zaK8gQWKmCXHlg==} + dev: false + + /infer-owner/1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: false + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /info-symbol/0.1.0: + resolution: {integrity: sha1-J4QdcoZ920JCzWEtecEGM4gcang=} + engines: {node: '>=0.10.0'} + dev: false + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /inquirer-autocomplete-prompt/1.4.0_inquirer@8.2.0: + resolution: {integrity: sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==} + engines: {node: '>=10'} + peerDependencies: + inquirer: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + inquirer: 8.2.0 + run-async: 2.4.1 + rxjs: 6.6.7 + dev: false + + /inquirer/7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + dev: false + + /inquirer/8.2.0: + resolution: {integrity: sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==} + engines: {node: '>=8.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.4.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + dev: false + + /internal-slot/1.0.3: + resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.1.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /ip-regex/2.1.0: + resolution: {integrity: sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=} + engines: {node: '>=4'} + dev: true + + /ip/1.1.5: + resolution: {integrity: sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=} + dev: false + + /is-accessor-descriptor/0.1.6: + resolution: {integrity: sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + + /is-accessor-descriptor/1.0.0: + resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + + /is-arrayish/0.2.1: + resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} + dev: true + + /is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.1 + dev: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-buffer/1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + /is-callable/1.2.4: + resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==} + engines: {node: '>= 0.4'} + dev: true + + /is-ci/2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + dependencies: + ci-info: 2.0.0 + dev: true + + /is-core-module/2.8.0: + resolution: {integrity: sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==} + dependencies: + has: 1.0.3 + + /is-data-descriptor/0.1.4: + resolution: {integrity: sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + + /is-data-descriptor/1.0.0: + resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + + /is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-descriptor/0.1.6: + resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 0.1.6 + is-data-descriptor: 0.1.4 + kind-of: 5.1.0 + + /is-descriptor/1.0.2: + resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 1.0.0 + is-data-descriptor: 1.0.0 + kind-of: 6.0.3 + + /is-docker/2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + optional: true + + /is-even/1.0.0: + resolution: {integrity: sha1-drUFX7rY0pSoa2qUkBXhyXtxfAY=} + engines: {node: '>=0.10.0'} + dependencies: + is-odd: 0.1.2 + dev: false + + /is-extendable/0.1.1: + resolution: {integrity: sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=} + engines: {node: '>=0.10.0'} + + /is-extendable/1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: false + + /is-generator-fn/2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-interactive/1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: false + + /is-lambda/1.0.1: + resolution: {integrity: sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=} + dev: false + + /is-lower-case/1.1.3: + resolution: {integrity: sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=} + dependencies: + lower-case: 1.1.4 + dev: false + + /is-negative-zero/2.0.1: + resolution: {integrity: sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object/1.0.6: + resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number/2.1.0: + resolution: {integrity: sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: false + + /is-number/3.0.0: + resolution: {integrity: sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + + /is-number/4.0.0: + resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-odd/0.1.2: + resolution: {integrity: sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc=} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + dev: false + + /is-path-cwd/2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + /is-path-inside/3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + /is-plain-obj/2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: false + + /is-plain-object/2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-self-closing/1.0.1: + resolution: {integrity: sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg==} + engines: {node: '>=0.12.0'} + dependencies: + self-closing-tags: 1.0.1 + dev: false + + /is-shared-array-buffer/1.0.1: + resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==} + dev: true + + /is-stream/1.1.0: + resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} + engines: {node: '>=0.10.0'} + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.2 + dev: true + + /is-typedarray/1.0.0: + resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} + dev: true + + /is-unicode-supported/0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: false + + /is-upper-case/1.1.2: + resolution: {integrity: sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=} + dependencies: + upper-case: 1.1.3 + dev: false + + /is-weakref/1.0.1: + resolution: {integrity: sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + /is-wsl/2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + optional: true + + /isarray/0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + dev: false + + /isarray/1.0.0: + resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + + /isbinaryfile/4.0.8: + resolution: {integrity: sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==} + engines: {node: '>= 8.0.0'} + dev: false + + /isexe/2.0.0: + resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} + + /isobject/0.2.0: + resolution: {integrity: sha1-o0MhkvObkQtfAsyYlIeDbscKqF4=} + engines: {node: '>=0.10.0'} + dev: false + + /isobject/2.1.0: + resolution: {integrity: sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + + /isobject/3.0.1: + resolution: {integrity: sha1-TkMekrEalzFjaqH5yNHMvP2reN8=} + engines: {node: '>=0.10.0'} + + /isstream/0.1.2: + resolution: {integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=} + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument/4.0.3: + resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.16.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument/5.1.0: + resolution: {integrity: sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.16.0 + '@babel/parser': 7.16.4 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps/4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.3 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports/3.1.1: + resolution: {integrity: sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jake/10.8.5: + resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.4 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.0.4 + dev: true + + /jest-changed-files/25.5.0: + resolution: {integrity: sha512-EOw9QEqapsDT7mKF162m8HFzRPbmP8qJQny6ldVOdOVBz3ACgPm/1nAn5fPQ/NDaYhX/AHkrGwwkCncpAVSXcw==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + execa: 3.4.0 + throat: 5.0.0 + dev: true + + /jest-config/25.4.0: + resolution: {integrity: sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/core': 7.16.0 + '@jest/test-sequencer': 25.5.4 + '@jest/types': 25.5.0 + babel-jest: 25.5.1_@babel+core@7.16.0 + chalk: 3.0.0 + deepmerge: 4.2.2 + glob: 7.2.0 + jest-environment-jsdom: 25.5.0 + jest-environment-node: 25.5.0 + jest-get-type: 25.2.6 + jest-jasmine2: 25.5.4 + jest-regex-util: 25.2.6 + jest-resolve: 25.5.1 + jest-util: 25.5.0 + jest-validate: 25.5.0 + micromatch: 4.0.4 + pretty-format: 25.5.0 + realpath-native: 2.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-config/25.5.4: + resolution: {integrity: sha512-SZwR91SwcdK6bz7Gco8qL7YY2sx8tFJYzvg216DLihTWf+LKY/DoJXpM9nTzYakSyfblbqeU48p/p7Jzy05Atg==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/core': 7.16.0 + '@jest/test-sequencer': 25.5.4 + '@jest/types': 25.5.0 + babel-jest: 25.5.1_@babel+core@7.16.0 + chalk: 3.0.0 + deepmerge: 4.2.2 + glob: 7.2.0 + graceful-fs: 4.2.8 + jest-environment-jsdom: 25.5.0 + jest-environment-node: 25.5.0 + jest-get-type: 25.2.6 + jest-jasmine2: 25.5.4 + jest-regex-util: 25.2.6 + jest-resolve: 25.5.1 + jest-util: 25.5.0 + jest-validate: 25.5.0 + micromatch: 4.0.4 + pretty-format: 25.5.0 + realpath-native: 2.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-diff/25.5.0: + resolution: {integrity: sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==} + engines: {node: '>= 8.3'} + dependencies: + chalk: 3.0.0 + diff-sequences: 25.2.6 + jest-get-type: 25.2.6 + pretty-format: 25.5.0 + dev: true + + /jest-diff/27.4.2: + resolution: {integrity: sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.4.0 + jest-get-type: 27.4.0 + pretty-format: 27.4.2 + dev: true + + /jest-docblock/25.3.0: + resolution: {integrity: sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==} + engines: {node: '>= 8.3'} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each/25.5.0: + resolution: {integrity: sha512-QBogUxna3D8vtiItvn54xXde7+vuzqRrEeaw8r1s+1TG9eZLVJE5ZkKoSUlqFwRjnlaA4hyKGiu9OlkFIuKnjA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + chalk: 3.0.0 + jest-get-type: 25.2.6 + jest-util: 25.5.0 + pretty-format: 25.5.0 + dev: true + + /jest-environment-jsdom/25.5.0: + resolution: {integrity: sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/environment': 25.5.0 + '@jest/fake-timers': 25.5.0 + '@jest/types': 25.5.0 + jest-mock: 25.5.0 + jest-util: 25.5.0 + jsdom: 15.2.1 + transitivePeerDependencies: + - bufferutil + - canvas + - utf-8-validate + dev: true + + /jest-environment-node/25.5.0: + resolution: {integrity: sha512-iuxK6rQR2En9EID+2k+IBs5fCFd919gVVK5BeND82fYeLWPqvRcFNPKu9+gxTwfB5XwBGBvZ0HFQa+cHtIoslA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/environment': 25.5.0 + '@jest/fake-timers': 25.5.0 + '@jest/types': 25.5.0 + jest-mock: 25.5.0 + jest-util: 25.5.0 + semver: 6.3.0 + dev: true + + /jest-get-type/25.2.6: + resolution: {integrity: sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==} + engines: {node: '>= 8.3'} + dev: true + + /jest-get-type/27.4.0: + resolution: {integrity: sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + + /jest-haste-map/25.5.1: + resolution: {integrity: sha512-dddgh9UZjV7SCDQUrQ+5t9yy8iEgKc1AKqZR9YDww8xsVOtzPQSMVLDChc21+g29oTRexb9/B0bIlZL+sWmvAQ==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + '@types/graceful-fs': 4.1.5 + anymatch: 3.1.2 + fb-watchman: 2.0.1 + graceful-fs: 4.2.8 + jest-serializer: 25.5.0 + jest-util: 25.5.0 + jest-worker: 25.5.0 + micromatch: 4.0.4 + sane: 4.1.0 + walker: 1.0.8 + which: 2.0.2 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /jest-jasmine2/25.5.4: + resolution: {integrity: sha512-9acbWEfbmS8UpdcfqnDO+uBUgKa/9hcRh983IHdM+pKmJPL77G0sWAAK0V0kr5LK3a8cSBfkFSoncXwQlRZfkQ==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/traverse': 7.16.3 + '@jest/environment': 25.5.0 + '@jest/source-map': 25.5.0 + '@jest/test-result': 25.5.0 + '@jest/types': 25.5.0 + chalk: 3.0.0 + co: 4.6.0 + expect: 25.5.0 + is-generator-fn: 2.1.0 + jest-each: 25.5.0 + jest-matcher-utils: 25.5.0 + jest-message-util: 25.5.0 + jest-runtime: 25.5.4 + jest-snapshot: 25.5.1 + jest-util: 25.5.0 + pretty-format: 25.5.0 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-leak-detector/25.5.0: + resolution: {integrity: sha512-rV7JdLsanS8OkdDpZtgBf61L5xZ4NnYLBq72r6ldxahJWWczZjXawRsoHyXzibM5ed7C2QRjpp6ypgwGdKyoVA==} + engines: {node: '>= 8.3'} + dependencies: + jest-get-type: 25.2.6 + pretty-format: 25.5.0 + dev: true + + /jest-matcher-utils/25.5.0: + resolution: {integrity: sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw==} + engines: {node: '>= 8.3'} + dependencies: + chalk: 3.0.0 + jest-diff: 25.5.0 + jest-get-type: 25.2.6 + pretty-format: 25.5.0 + dev: true + + /jest-message-util/25.5.0: + resolution: {integrity: sha512-ezddz3YCT/LT0SKAmylVyWWIGYoKHOFOFXx3/nA4m794lfVUskMcwhip6vTgdVrOtYdjeQeis2ypzes9mZb4EA==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/code-frame': 7.16.0 + '@jest/types': 25.5.0 + '@types/stack-utils': 1.0.1 + chalk: 3.0.0 + graceful-fs: 4.2.8 + micromatch: 4.0.4 + slash: 3.0.0 + stack-utils: 1.0.5 + dev: true + + /jest-mock/25.5.0: + resolution: {integrity: sha512-eXWuTV8mKzp/ovHc5+3USJMYsTBhyQ+5A1Mak35dey/RG8GlM4YWVylZuGgVXinaW6tpvk/RSecmF37FKUlpXA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + dev: true + + /jest-pnp-resolver/1.2.2_jest-resolve@25.5.1: + resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 25.5.1 + dev: true + + /jest-regex-util/25.2.6: + resolution: {integrity: sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==} + engines: {node: '>= 8.3'} + dev: true + + /jest-resolve-dependencies/25.5.4: + resolution: {integrity: sha512-yFmbPd+DAQjJQg88HveObcGBA32nqNZ02fjYmtL16t1xw9bAttSn5UGRRhzMHIQbsep7znWvAvnD4kDqOFM0Uw==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + jest-regex-util: 25.2.6 + jest-snapshot: 25.5.1 + dev: true + + /jest-resolve/25.5.1: + resolution: {integrity: sha512-Hc09hYch5aWdtejsUZhA+vSzcotf7fajSlPA6EZPE1RmPBAD39XtJhvHWFStid58iit4IPDLI/Da4cwdDmAHiQ==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + browser-resolve: 1.11.3 + chalk: 3.0.0 + graceful-fs: 4.2.8 + jest-pnp-resolver: 1.2.2_jest-resolve@25.5.1 + read-pkg-up: 7.0.1 + realpath-native: 2.0.0 + resolve: 1.20.0 + slash: 3.0.0 + dev: true + + /jest-runner/25.5.4: + resolution: {integrity: sha512-V/2R7fKZo6blP8E9BL9vJ8aTU4TH2beuqGNxHbxi6t14XzTb+x90B3FRgdvuHm41GY8ch4xxvf0ATH4hdpjTqg==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/console': 25.5.0 + '@jest/environment': 25.5.0 + '@jest/test-result': 25.5.0 + '@jest/types': 25.5.0 + chalk: 3.0.0 + exit: 0.1.2 + graceful-fs: 4.2.8 + jest-config: 25.5.4 + jest-docblock: 25.3.0 + jest-haste-map: 25.5.1 + jest-jasmine2: 25.5.4 + jest-leak-detector: 25.5.0 + jest-message-util: 25.5.0 + jest-resolve: 25.5.1 + jest-runtime: 25.5.4 + jest-util: 25.5.0 + jest-worker: 25.5.0 + source-map-support: 0.5.21 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-runtime/25.5.4: + resolution: {integrity: sha512-RWTt8LeWh3GvjYtASH2eezkc8AehVoWKK20udV6n3/gC87wlTbE1kIA+opCvNWyyPeBs6ptYsc6nyHUb1GlUVQ==} + engines: {node: '>= 8.3'} + hasBin: true + dependencies: + '@jest/console': 25.5.0 + '@jest/environment': 25.5.0 + '@jest/globals': 25.5.2 + '@jest/source-map': 25.5.0 + '@jest/test-result': 25.5.0 + '@jest/transform': 25.5.1 + '@jest/types': 25.5.0 + '@types/yargs': 15.0.14 + chalk: 3.0.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.0 + graceful-fs: 4.2.8 + jest-config: 25.5.4 + jest-haste-map: 25.5.1 + jest-message-util: 25.5.0 + jest-mock: 25.5.0 + jest-regex-util: 25.2.6 + jest-resolve: 25.5.1 + jest-snapshot: 25.5.1 + jest-util: 25.5.0 + jest-validate: 25.5.0 + realpath-native: 2.0.0 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-serializer/25.5.0: + resolution: {integrity: sha512-LxD8fY1lByomEPflwur9o4e2a5twSQ7TaVNLlFUuToIdoJuBt8tzHfCsZ42Ok6LkKXWzFWf3AGmheuLAA7LcCA==} + engines: {node: '>= 8.3'} + dependencies: + graceful-fs: 4.2.8 + dev: true + + /jest-snapshot/25.4.0: + resolution: {integrity: sha512-J4CJ0X2SaGheYRZdLz9CRHn9jUknVmlks4UBeu270hPAvdsauFXOhx9SQP2JtRzhnR3cvro/9N9KP83/uvFfRg==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/types': 7.16.0 + '@jest/types': 25.5.0 + '@types/prettier': 1.19.1 + chalk: 3.0.0 + expect: 25.5.0 + jest-diff: 25.5.0 + jest-get-type: 25.2.6 + jest-matcher-utils: 25.5.0 + jest-message-util: 25.5.0 + jest-resolve: 25.5.1 + make-dir: 3.1.0 + natural-compare: 1.4.0 + pretty-format: 25.5.0 + semver: 6.3.0 + dev: true + + /jest-snapshot/25.5.1: + resolution: {integrity: sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ==} + engines: {node: '>= 8.3'} + dependencies: + '@babel/types': 7.16.0 + '@jest/types': 25.5.0 + '@types/prettier': 1.19.1 + chalk: 3.0.0 + expect: 25.5.0 + graceful-fs: 4.2.8 + jest-diff: 25.5.0 + jest-get-type: 25.2.6 + jest-matcher-utils: 25.5.0 + jest-message-util: 25.5.0 + jest-resolve: 25.5.1 + make-dir: 3.1.0 + natural-compare: 1.4.0 + pretty-format: 25.5.0 + semver: 6.3.0 + dev: true + + /jest-util/25.5.0: + resolution: {integrity: sha512-KVlX+WWg1zUTB9ktvhsg2PXZVdkI1NBevOJSkTKYAyXyH4QSvh+Lay/e/v+bmaFfrkfx43xD8QTfgobzlEXdIA==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + chalk: 3.0.0 + graceful-fs: 4.2.8 + is-ci: 2.0.0 + make-dir: 3.1.0 + dev: true + + /jest-validate/25.5.0: + resolution: {integrity: sha512-okUFKqhZIpo3jDdtUXUZ2LxGUZJIlfdYBvZb1aczzxrlyMlqdnnws9MOxezoLGhSaFc2XYaHNReNQfj5zPIWyQ==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + camelcase: 5.3.1 + chalk: 3.0.0 + jest-get-type: 25.2.6 + leven: 3.1.0 + pretty-format: 25.5.0 + dev: true + + /jest-watcher/25.5.0: + resolution: {integrity: sha512-XrSfJnVASEl+5+bb51V0Q7WQx65dTSk7NL4yDdVjPnRNpM0hG+ncFmDYJo9O8jaSRcAitVbuVawyXCRoxGrT5Q==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/test-result': 25.5.0 + '@jest/types': 25.5.0 + ansi-escapes: 4.3.2 + chalk: 3.0.0 + jest-util: 25.5.0 + string-length: 3.1.0 + dev: true + + /jest-worker/25.5.0: + resolution: {integrity: sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==} + engines: {node: '>= 8.3'} + dependencies: + merge-stream: 2.0.0 + supports-color: 7.2.0 + dev: true + + /jju/1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsbn/0.1.1: + resolution: {integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM=} + dev: true + + /jsdom/15.2.1: + resolution: {integrity: sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==} + engines: {node: '>=8'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.5 + acorn: 7.4.1 + acorn-globals: 4.3.4 + array-equal: 1.0.0 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 1.1.0 + domexception: 1.0.1 + escodegen: 1.14.3 + html-encoding-sniffer: 1.0.2 + nwsapi: 2.2.0 + parse5: 5.1.0 + pn: 1.1.0 + request: 2.88.2 + request-promise-native: 1.0.9_request@2.88.2 + saxes: 3.1.11 + symbol-tree: 3.2.4 + tough-cookie: 3.0.1 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 1.1.2 + webidl-conversions: 4.0.2 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 7.1.0 + ws: 7.5.6 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse/1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-schema/0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json-stringify-safe/5.0.1: + resolution: {integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=} + dev: true + + /json2md/2.0.0: + resolution: {integrity: sha512-4PIMtD0zTfQZWcUId1EyHY2BQ2EG/imHWHkGFbXYPlczW8G6wPJA/BRVN3e5v6NPwFUCcoFvUsCeo6rzV2CWww==} + dependencies: + indento: 1.1.13 + dev: false + + /json5/2.2.0: + resolution: {integrity: sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + minimist: 1.2.5 + dev: true + + /jsonfile/4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.8 + + /jsonfile/6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.8 + dev: false + + /jsonparse/1.3.1: + resolution: {integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=} + engines: {'0': node >= 0.2.0} + dev: false + + /jsonpath-plus/4.0.0: + resolution: {integrity: sha512-e0Jtg4KAzDJKKwzbLaUtinCn0RZseWBVRTRGihSpvFlM3wTR7ExSp+PTdeTsDrLNJUe7L7JYJe8mblHX5SCT6A==} + engines: {node: '>=10.0'} + dev: true + + /jsprim/1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: true + + /jsx-ast-utils/2.4.1: + resolution: {integrity: sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.4 + object.assign: 4.1.2 + dev: true + + /kind-of/3.2.2: + resolution: {integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + + /kind-of/4.0.0: + resolution: {integrity: sha1-IIE989cSkosgc3hpGkUGb65y3Vc=} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + + /kind-of/5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + /lazy-cache/2.0.2: + resolution: {integrity: sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=} + engines: {node: '>=0.10.0'} + dependencies: + set-getter: 0.1.1 + dev: false + + /leven/3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /levn/0.3.0: + resolution: {integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: true + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig/2.0.4: + resolution: {integrity: sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==} + engines: {node: '>=10'} + dev: false + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /lint-staged/12.3.4: + resolution: {integrity: sha512-yv/iK4WwZ7/v0GtVkNb3R82pdL9M+ScpIbJLJNyCXkJ1FGaXvRCOg/SeL59SZtPpqZhE7BD6kPKFLIDUhDx2/w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dependencies: + cli-truncate: 3.1.0 + colorette: 2.0.16 + commander: 8.3.0 + debug: 4.3.3_supports-color@9.2.1 + execa: 5.1.1 + lilconfig: 2.0.4 + listr2: 4.0.2 + micromatch: 4.0.4 + normalize-path: 3.0.0 + object-inspect: 1.12.0 + string-argv: 0.3.1 + supports-color: 9.2.1 + yaml: 1.10.2 + transitivePeerDependencies: + - enquirer + dev: false + + /listr2/4.0.2: + resolution: {integrity: sha512-YcgwfCWpvPbj9FLUGqvdFvd3hrFWKpOeuXznRgfWEJ7RNr8b/IKKIKZABHx3aU+4CWN/iSAFFSReziQG6vTeIA==} + engines: {node: '>=12'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.16 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.0 + rxjs: 7.5.2 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: false + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: false + + /lodash._reinterpolate/3.0.0: + resolution: {integrity: sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=} + dev: false + + /lodash.get/4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + + /lodash.isequal/4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.sortby/4.7.0: + resolution: {integrity: sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=} + dev: true + + /lodash.template/4.5.0: + resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + dependencies: + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 + dev: false + + /lodash.templatesettings/4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + dependencies: + lodash._reinterpolate: 3.0.0 + dev: false + + /lodash.truncate/4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-ok/0.1.1: + resolution: {integrity: sha1-vqPdNqzQuKckDXhza1uXxlREozQ=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-green: 0.1.1 + success-symbol: 0.1.0 + dev: false + + /log-symbols/4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: false + + /log-update/4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: false + + /log-utils/0.2.1: + resolution: {integrity: sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-colors: 0.2.0 + error-symbol: 0.1.0 + info-symbol: 0.1.0 + log-ok: 0.1.1 + success-symbol: 0.1.0 + time-stamp: 1.1.0 + warning-symbol: 0.1.0 + dev: false + + /logging-helpers/1.0.0: + resolution: {integrity: sha512-qyIh2goLt1sOgQQrrIWuwkRjUx4NUcEqEGAcYqD8VOnOC6ItwkrVE8/tA4smGpjzyp4Svhc6RodDp9IO5ghpyA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + log-utils: 0.2.1 + dev: false + + /lolex/5.1.2: + resolution: {integrity: sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==} + dependencies: + '@sinonjs/commons': 1.8.3 + dev: true + + /loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: true + + /lower-case-first/1.0.2: + resolution: {integrity: sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=} + dependencies: + lower-case: 1.1.4 + dev: false + + /lower-case/1.1.4: + resolution: {integrity: sha1-miyr0bno4K6ZOkv31YdcOcQujqw=} + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + + /make-fetch-happen/9.1.0: + resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} + engines: {node: '>= 10'} + dependencies: + agentkeepalive: 4.1.4 + cacache: 15.3.0 + http-cache-semantics: 4.1.0 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.0 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.1.5 + minipass-collect: 1.0.2 + minipass-fetch: 1.4.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.2 + promise-retry: 2.0.1 + socks-proxy-agent: 6.1.1 + ssri: 8.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /makeerror/1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + + /map-cache/0.2.2: + resolution: {integrity: sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=} + engines: {node: '>=0.10.0'} + + /map-canvas/0.1.5: + resolution: {integrity: sha512-f7M3sOuL9+up0NCOZbb1rQpWDLZwR/ftCiNbyscjl9LUUEwrRaoumH4sz6swgs58lF21DQ0hsYOCw5C6Zz7hbg==} + dependencies: + drawille-canvas-blessed-contrib: 0.1.3 + xml2js: 0.4.23 + dev: false + + /map-visit/1.0.0: + resolution: {integrity: sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + + /marked-terminal/5.1.1_marked@4.2.12: + resolution: {integrity: sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==} + engines: {node: '>=14.13.1 || >=16.0.0'} + peerDependencies: + marked: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + dependencies: + ansi-escapes: 5.0.0 + cardinal: 2.1.1 + chalk: 5.2.0 + cli-table3: 0.6.3 + marked: 4.2.12 + node-emoji: 1.11.0 + supports-hyperlinks: 2.2.0 + dev: false + + /marked/4.2.12: + resolution: {integrity: sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==} + engines: {node: '>= 12'} + hasBin: true + dev: false + + /memory-streams/0.1.3: + resolution: {integrity: sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==} + dependencies: + readable-stream: 1.0.34 + dev: false + + /memorystream/0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + dev: false + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + /micromatch/3.1.10: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + + /micromatch/4.0.4: + resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.0 + + /mime-db/1.51.0: + resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types/2.1.34: + resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.51.0 + dev: true + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + /minimatch/3.0.4: + resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + dependencies: + brace-expansion: 1.1.11 + + /minimatch/5.1.1: + resolution: {integrity: sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + + /minimist/1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + + /minipass-collect/1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.5 + dev: false + + /minipass-fetch/1.4.1: + resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} + engines: {node: '>=8'} + dependencies: + minipass: 3.1.5 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: false + + /minipass-flush/1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.5 + dev: false + + /minipass-json-stream/1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + dependencies: + jsonparse: 1.3.1 + minipass: 3.1.5 + dev: false + + /minipass-pipeline/1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.1.5 + dev: false + + /minipass-sized/1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + dependencies: + minipass: 3.1.5 + dev: false + + /minipass/3.1.5: + resolution: {integrity: sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minizlib/2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.5 + yallist: 4.0.0 + dev: false + + /mixin-deep/1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + /mkdirp/0.5.5: + resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} + hasBin: true + dependencies: + minimist: 1.2.5 + dev: false + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /moment/2.29.1: + resolution: {integrity: sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==} + dev: false + + /ms/2.0.0: + resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /mute-stream/0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: false + + /nanomatch/1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /negotiator/0.6.2: + resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==} + engines: {node: '>= 0.6'} + dev: false + + /neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /nice-try/1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: true + + /no-case/2.3.2: + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + dependencies: + lower-case: 1.1.4 + dev: false + + /node-emoji/1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + dependencies: + lodash: 4.17.21 + dev: false + + /node-gyp/8.4.1: + resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} + engines: {node: '>= 10.12.0'} + hasBin: true + dependencies: + env-paths: 2.2.1 + glob: 7.2.0 + graceful-fs: 4.2.8 + make-fetch-happen: 9.1.0 + nopt: 5.0.0 + npmlog: 6.0.0 + rimraf: 3.0.2 + semver: 7.3.5 + tar: 6.1.11 + which: 2.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /node-int64/0.4.0: + resolution: {integrity: sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=} + dev: true + + /node-notifier/6.0.0: + resolution: {integrity: sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==} + requiresBuild: true + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 6.3.0 + shellwords: 0.1.1 + which: 1.3.1 + dev: true + optional: true + + /node-plop/0.26.3: + resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} + engines: {node: '>=8.9.4'} + dependencies: + '@babel/runtime-corejs3': 7.16.5 + '@types/inquirer': 6.5.0 + change-case: 3.1.0 + del: 5.1.0 + globby: 10.0.2 + handlebars: 4.7.7 + inquirer: 7.3.3 + isbinaryfile: 4.0.8 + lodash.get: 4.4.2 + mkdirp: 0.5.5 + resolve: 1.20.0 + dev: false + + /node-releases/2.0.1: + resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} + dev: true + + /nopt/2.1.2: + resolution: {integrity: sha512-x8vXm7BZ2jE1Txrxh/hO74HTuYZQEbo8edoRcANgdZ4+PCV+pbjd/xdummkmjjC7LU5EjPzlu8zEq/oxWylnKA==} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /nopt/5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.20.0 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.0 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + /npm-bundled/1.1.2: + resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} + dependencies: + npm-normalize-package-bin: 1.0.1 + dev: false + + /npm-install-checks/4.0.0: + resolution: {integrity: sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==} + engines: {node: '>=10'} + dependencies: + semver: 7.3.5 + dev: false + + /npm-normalize-package-bin/1.0.1: + resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} + dev: false + + /npm-package-arg/8.1.5: + resolution: {integrity: sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.0.2 + semver: 7.3.5 + validate-npm-package-name: 3.0.0 + dev: false + + /npm-packlist/3.0.0: + resolution: {integrity: sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + glob: 7.2.0 + ignore-walk: 4.0.1 + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 + dev: false + + /npm-pick-manifest/6.1.1: + resolution: {integrity: sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==} + dependencies: + npm-install-checks: 4.0.0 + npm-normalize-package-bin: 1.0.1 + npm-package-arg: 8.1.5 + semver: 7.3.5 + dev: false + + /npm-registry-fetch/11.0.0: + resolution: {integrity: sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==} + engines: {node: '>=10'} + dependencies: + make-fetch-happen: 9.1.0 + minipass: 3.1.5 + minipass-fetch: 1.4.1 + minipass-json-stream: 1.0.1 + minizlib: 2.1.2 + npm-package-arg: 8.1.5 + transitivePeerDependencies: + - supports-color + dev: false + + /npm-run-path/2.0.2: + resolution: {integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + + /npmlog/6.0.0: + resolution: {integrity: sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 4.0.0 + set-blocking: 2.0.0 + dev: false + + /nwsapi/2.2.0: + resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==} + dev: true + + /oauth-sign/0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + dev: true + + /object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-copy/0.1.0: + resolution: {integrity: sha1-fn2Fi3gb18mRpBupde04EnVOmYw=} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + /object-inspect/1.12.0: + resolution: {integrity: sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==} + + /object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object-visit/1.0.1: + resolution: {integrity: sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + + /object.assign/4.1.2: + resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + has-symbols: 1.0.2 + object-keys: 1.1.1 + dev: true + + /object.entries/1.1.5: + resolution: {integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + dev: true + + /object.fromentries/2.0.5: + resolution: {integrity: sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + dev: true + + /object.pick/1.3.0: + resolution: {integrity: sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + + /object.values/1.1.5: + resolution: {integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + + /optimist/0.2.8: + resolution: {integrity: sha512-Wy7E3cQDpqsTIFyW7m22hSevyTLxw850ahYv7FWsw4G6MIKVTZ8NSA95KBrQ95a4SMsMr1UGUUnwEFKhVaSzIg==} + dependencies: + wordwrap: 0.0.3 + dev: false + + /optimist/0.3.7: + resolution: {integrity: sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==} + dependencies: + wordwrap: 0.0.3 + dev: false + + /optionator/0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.3 + dev: true + + /optionator/0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /ora/5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: false + + /os-tmpdir/1.0.2: + resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} + engines: {node: '>=0.10.0'} + dev: false + + /p-each-series/2.2.0: + resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} + engines: {node: '>=8'} + dev: true + + /p-finally/1.0.0: + resolution: {integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=} + engines: {node: '>=4'} + dev: true + + /p-finally/2.0.1: + resolution: {integrity: sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==} + engines: {node: '>=8'} + dev: true + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: false + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: false + + /p-map/3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + dependencies: + aggregate-error: 3.1.0 + dev: false + + /p-map/4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /pacote/12.0.2: + resolution: {integrity: sha512-Ar3mhjcxhMzk+OVZ8pbnXdb0l8+pimvlsqBGRNkble2NVgyqOGE3yrCGi/lAYq7E7NRDMz89R1Wx5HIMCGgeYg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + hasBin: true + dependencies: + '@npmcli/git': 2.1.0 + '@npmcli/installed-package-contents': 1.0.7 + '@npmcli/promise-spawn': 1.3.2 + '@npmcli/run-script': 2.0.0 + cacache: 15.3.0 + chownr: 2.0.0 + fs-minipass: 2.1.0 + infer-owner: 1.0.4 + minipass: 3.1.5 + mkdirp: 1.0.4 + npm-package-arg: 8.1.5 + npm-packlist: 3.0.0 + npm-pick-manifest: 6.1.1 + npm-registry-fetch: 11.0.0 + promise-retry: 2.0.1 + read-package-json-fast: 2.0.3 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.1.11 + transitivePeerDependencies: + - supports-color + dev: false + + /param-case/2.1.1: + resolution: {integrity: sha1-35T9jPZTHs915r75oIWPvHK+Ikc=} + dependencies: + no-case: 2.3.2 + dev: false + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.16.0 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse5/5.1.0: + resolution: {integrity: sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==} + dev: true + + /pascal-case/2.0.1: + resolution: {integrity: sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=} + dependencies: + camel-case: 3.0.0 + upper-case-first: 1.1.2 + dev: false + + /pascalcase/0.1.1: + resolution: {integrity: sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=} + engines: {node: '>=0.10.0'} + + /path-case/2.1.1: + resolution: {integrity: sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=} + dependencies: + no-case: 2.3.2 + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + /path-key/2.0.1: + resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=} + engines: {node: '>=4'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + /performance-now/2.1.0: + resolution: {integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.0: + resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} + engines: {node: '>=8.6'} + + /picture-tuber/1.0.2: + resolution: {integrity: sha512-49/xq+wzbwDeI32aPvwQJldM8pr7dKDRuR76IjztrkmiCkAQDaWFJzkmfVqCHmt/iFoPFhHmI9L0oKhthrTOQw==} + engines: {node: '>=0.4.0'} + hasBin: true + dependencies: + buffers: 0.1.1 + charm: 0.1.2 + event-stream: 0.9.8 + optimist: 0.3.7 + png-js: 0.1.1 + x256: 0.0.2 + dev: false + + /pirates/4.0.4: + resolution: {integrity: sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==} + engines: {node: '>= 6'} + dev: true + + /pn/1.1.0: + resolution: {integrity: sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==} + dev: true + + /png-js/0.1.1: + resolution: {integrity: sha512-NTtk2SyfjBm+xYl2/VZJBhFnTQ4kU5qWC7VC4/iGbrgiU4FuB4xC+74erxADYJIqZICOR1HCvRA7EBHkpjTg9g==} + dev: false + + /posix-character-classes/0.1.1: + resolution: {integrity: sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=} + engines: {node: '>=0.10.0'} + + /prelude-ls/1.1.2: + resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=} + engines: {node: '>= 0.8.0'} + dev: true + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier/2.3.2: + resolution: {integrity: sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-format/25.5.0: + resolution: {integrity: sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==} + engines: {node: '>= 8.3'} + dependencies: + '@jest/types': 25.5.0 + ansi-regex: 5.0.1 + ansi-styles: 4.3.0 + react-is: 16.13.1 + dev: true + + /pretty-format/27.4.2: + resolution: {integrity: sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.4.2 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /progress/2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + + /promise-inflight/1.0.1: + resolution: {integrity: sha1-mEcocL8igTL8vdhoEputEsPAKeM=} + dev: false + + /promise-retry/2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + dev: false + + /prop-types/15.7.2: + resolution: {integrity: sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: true + + /psl/1.8.0: + resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==} + dev: true + + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /qs/6.5.2: + resolution: {integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==} + engines: {node: '>=0.6'} + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + /react-is/16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: true + + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + + /read-package-json-fast/2.0.3: + resolution: {integrity: sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==} + engines: {node: '>=10'} + dependencies: + json-parse-even-better-errors: 2.3.1 + npm-normalize-package-bin: 1.0.1 + dev: false + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream/1.0.34: + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + dev: false + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp/3.5.0: + resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.0 + dev: true + + /realpath-native/2.0.0: + resolution: {integrity: sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==} + engines: {node: '>=8'} + dev: true + + /redeyed/2.1.1: + resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} + dependencies: + esprima: 4.0.1 + dev: false + + /regenerator-runtime/0.13.9: + resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} + dev: false + + /regex-not/1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + /regexp.prototype.flags/1.3.1: + resolution: {integrity: sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /relative/3.0.2: + resolution: {integrity: sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8=} + engines: {node: '>= 0.8.0'} + dependencies: + isobject: 2.1.0 + dev: false + + /remarkable/1.7.4: + resolution: {integrity: sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==} + engines: {node: '>= 0.10.0'} + hasBin: true + dependencies: + argparse: 1.0.10 + autolinker: 0.28.1 + dev: false + + /remove-trailing-separator/1.1.0: + resolution: {integrity: sha1-wkvOKig62tW8P1jg1IJJuSN52O8=} + dev: true + + /repeat-element/1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + + /repeat-string/1.6.1: + resolution: {integrity: sha1-jcrkcOHIirwtYA//Sndihtp15jc=} + engines: {node: '>=0.10'} + + /request-promise-core/1.1.4_request@2.88.2: + resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + dependencies: + lodash: 4.17.21 + request: 2.88.2 + dev: true + + /request-promise-native/1.0.9_request@2.88.2: + resolution: {integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==} + engines: {node: '>=0.12.0'} + deprecated: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + dependencies: + request: 2.88.2 + request-promise-core: 1.1.4_request@2.88.2 + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + dev: true + + /request/2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.11.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.34 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.2 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + dev: true + + /require-directory/2.1.1: + resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} + engines: {node: '>=0.10.0'} + + /require-from-string/2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename/2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-url/0.2.1: + resolution: {integrity: sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=} + deprecated: https://github.com/lydell/resolve-url#deprecated + + /resolve/1.1.7: + resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} + dev: true + + /resolve/1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + dependencies: + path-parse: 1.0.7 + + /resolve/1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.8.0 + path-parse: 1.0.7 + dev: true + + /resolve/1.20.0: + resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==} + dependencies: + is-core-module: 2.8.0 + path-parse: 1.0.7 + + /restore-cursor/3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.6 + dev: false + + /ret/0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + /retry/0.12.0: + resolution: {integrity: sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=} + engines: {node: '>= 4'} + dev: false + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + /rfdc/1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: false + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.0 + + /rsvp/4.8.5: + resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} + engines: {node: 6.* || >= 7.*} + dev: true + + /run-async/2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: false + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + + /rxjs/6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: false + + /rxjs/7.4.0: + resolution: {integrity: sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==} + dependencies: + tslib: 2.1.0 + + /rxjs/7.5.2: + resolution: {integrity: sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==} + dependencies: + tslib: 2.3.1 + dev: false + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + /safe-regex/1.1.0: + resolution: {integrity: sha1-QKNmnzsHfR6UPURinhV91IAjvy4=} + dependencies: + ret: 0.1.15 + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + /sane/4.1.0: + resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} + engines: {node: 6.* || 8.* || >= 10.*} + deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added + hasBin: true + dependencies: + '@cnakazawa/watch': 1.0.4 + anymatch: 2.0.0 + capture-exit: 2.0.0 + exec-sh: 0.3.6 + execa: 1.0.0 + fb-watchman: 2.0.1 + micromatch: 3.1.10 + minimist: 1.2.5 + walker: 1.0.8 + dev: true + + /sax/1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: false + + /saxes/3.1.11: + resolution: {integrity: sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==} + engines: {node: '>=8'} + dependencies: + xmlchars: 2.2.0 + dev: true + + /self-closing-tags/1.0.1: + resolution: {integrity: sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA==} + engines: {node: '>=0.12.0'} + dev: false + + /semver/5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver/7.3.5: + resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /sentence-case/2.1.1: + resolution: {integrity: sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=} + dependencies: + no-case: 2.3.2 + upper-case-first: 1.1.2 + dev: false + + /set-blocking/2.0.0: + resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} + + /set-getter/0.1.1: + resolution: {integrity: sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==} + engines: {node: '>=0.10.0'} + dependencies: + to-object-path: 0.3.0 + dev: false + + /set-value/2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + + /shebang-command/1.2.0: + resolution: {integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex/1.0.0: + resolution: {integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=} + engines: {node: '>=0.10.0'} + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /shellwords/0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + dev: true + optional: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.1 + object-inspect: 1.12.0 + dev: true + + /signal-exit/3.0.6: + resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==} + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + /slice-ansi/3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: false + + /slice-ansi/4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.1.0 + is-fullwidth-code-point: 4.0.0 + dev: false + + /smart-buffer/4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + + /snake-case/2.1.0: + resolution: {integrity: sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=} + dependencies: + no-case: 2.3.2 + dev: false + + /snapdragon-node/2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + /snapdragon-util/3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + + /snapdragon/0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + + /socks-proxy-agent/6.1.1: + resolution: {integrity: sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.3 + socks: 2.6.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socks/2.6.1: + resolution: {integrity: sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 1.1.5 + smart-buffer: 4.2.0 + dev: false + + /sort-object-keys/1.1.3: + resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} + dev: false + + /sort-package-json/1.54.0: + resolution: {integrity: sha512-MA0nRiSfZ4/CNM/9rz70Hwq4PpvtBc3v532tzQSmoaLSdeBB3cCd488xmNruLL0fb/ZdbKlcaDDudwnrObbjBw==} + hasBin: true + dependencies: + detect-indent: 6.1.0 + detect-newline: 3.1.0 + git-hooks-list: 1.0.3 + globby: 10.0.0 + is-plain-obj: 2.1.0 + sort-object-keys: 1.1.3 + dev: false + + /source-map-resolve/0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.0 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + + /source-map-support/0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map-url/0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + + /source-map/0.5.7: + resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=} + engines: {node: '>=0.10.0'} + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + /source-map/0.7.3: + resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} + engines: {node: '>= 8'} + dev: true + + /sparkline/0.1.2: + resolution: {integrity: sha512-t//aVOiWt9fi/e22ea1vXVWBDX+gp18y+Ch9sKqmHl828bRfvP2VtfTJVEcgWFBQHd0yDPNQRiHdqzCvbcYSDA==} + engines: {node: '>= 0.8.0'} + hasBin: true + dependencies: + here: 0.0.2 + nopt: 2.1.2 + dev: false + + /spdx-correct/3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-license-ids/3.0.11: + resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} + dev: true + + /split-string/3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + /sshpk/1.16.1: + resolution: {integrity: sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: true + + /ssri/8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.5 + dev: false + + /stack-utils/1.0.5: + resolution: {integrity: sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /static-extend/0.1.2: + resolution: {integrity: sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + /stealthy-require/1.1.1: + resolution: {integrity: sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=} + engines: {node: '>=0.10.0'} + dev: true + + /string-argv/0.3.1: + resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} + engines: {node: '>=0.6.19'} + + /string-length/3.1.0: + resolution: {integrity: sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==} + engines: {node: '>=8'} + dependencies: + astral-regex: 1.0.0 + strip-ansi: 5.2.0 + dev: true + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + /string-width/5.1.0: + resolution: {integrity: sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 + dev: false + + /string.prototype.matchall/4.0.6: + resolution: {integrity: sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + es-abstract: 1.19.1 + get-intrinsic: 1.1.1 + has-symbols: 1.0.2 + internal-slot: 1.0.3 + regexp.prototype.flags: 1.3.1 + side-channel: 1.0.4 + dev: true + + /string.prototype.trimend/1.0.4: + resolution: {integrity: sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + dev: true + + /string.prototype.trimstart/1.0.4: + resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.3 + dev: true + + /string_decoder/0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + dev: false + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi/3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: false + + /strip-ansi/5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + dependencies: + ansi-regex: 4.1.0 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-eof/1.0.0: + resolution: {integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=} + engines: {node: '>=0.10.0'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /striptags/3.2.0: + resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==} + dev: false + + /success-symbol/0.1.0: + resolution: {integrity: sha1-JAIuSG878c3KCUKDt2nEctO3KJc=} + engines: {node: '>=0.10.0'} + dev: false + + /supports-color/2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: false + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-color/9.2.1: + resolution: {integrity: sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==} + engines: {node: '>=12'} + dev: false + + /supports-hyperlinks/2.2.0: + resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + /swap-case/1.1.2: + resolution: {integrity: sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=} + dependencies: + lower-case: 1.1.4 + upper-case: 1.1.3 + dev: false + + /symbol-tree/3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /table/6.7.5: + resolution: {integrity: sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.8.2 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /tapable/1.1.3: + resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} + engines: {node: '>=6'} + dev: true + + /tapable/2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: false + + /tar/6.1.11: + resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} + engines: {node: '>= 10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 3.1.5 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + + /term-canvas/0.0.5: + resolution: {integrity: sha512-eZ3rIWi5yLnKiUcsW8P79fKyooaLmyLWAGqBhFspqMxRNUiB4GmHHk5AzQ4LxvFbJILaXqQZLwbbATLOhCFwkw==} + dev: false + + /terminal-link/2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.2.0 + dev: true + + /test-exclude/6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.0 + minimatch: 3.0.4 + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /throat/5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + dev: true + + /through/2.3.8: + resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} + dev: false + + /through2/2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.7 + xtend: 4.0.2 + dev: false + + /time-stamp/1.1.0: + resolution: {integrity: sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=} + engines: {node: '>=0.10.0'} + dev: false + + /timsort/0.3.0: + resolution: {integrity: sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==} + + /title-case/2.1.1: + resolution: {integrity: sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=} + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + dev: false + + /tmp/0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: false + + /tmpl/1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} + engines: {node: '>=4'} + dev: true + + /to-gfm-code-block/0.1.1: + resolution: {integrity: sha1-JdBFpfrlUxielje1kJANpzLYqoI=} + engines: {node: '>=0.10.0'} + dev: false + + /to-object-path/0.3.0: + resolution: {integrity: sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + + /to-regex-range/2.1.1: + resolution: {integrity: sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /to-regex/3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + + /tough-cookie/2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + dependencies: + psl: 1.8.0 + punycode: 2.1.1 + dev: true + + /tough-cookie/3.0.1: + resolution: {integrity: sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==} + engines: {node: '>=6'} + dependencies: + ip-regex: 2.1.0 + psl: 1.8.0 + punycode: 2.1.1 + dev: true + + /tr46/1.0.1: + resolution: {integrity: sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=} + dependencies: + punycode: 2.1.1 + dev: true + + /true-case-path/2.2.1: + resolution: {integrity: sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==} + dev: true + + /ts-node/10.4.0_06c0d17a2604b53f6f8299daedda05cf: + resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.7.0 + '@tsconfig/node10': 1.0.8 + '@tsconfig/node12': 1.0.9 + '@tsconfig/node14': 1.0.1 + '@tsconfig/node16': 1.0.2 + '@types/node': 12.20.24 + acorn: 8.6.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.4.2 + yn: 3.1.1 + dev: false + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + /tslib/2.1.0: + resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==} + + /tslib/2.3.1: + resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} + dev: false + + /tsutils/3.21.0_typescript@4.4.2: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.4.2 + dev: true + + /tunnel-agent/0.6.0: + resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /tweetnacl/0.14.5: + resolution: {integrity: sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=} + dev: true + + /type-check/0.3.2: + resolution: {integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + dev: true + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest/1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: false + + /typedarray-to-buffer/3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /typeof-article/0.1.1: + resolution: {integrity: sha1-nwfnM8P7tkb/qeYcCN66zUYOBq8=} + engines: {node: '>=4'} + dependencies: + kind-of: 3.2.2 + dev: false + + /typescript/4.4.2: + resolution: {integrity: sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uglify-js/3.14.5: + resolution: {integrity: sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /unbox-primitive/1.0.1: + resolution: {integrity: sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==} + dependencies: + function-bind: 1.1.1 + has-bigints: 1.0.1 + has-symbols: 1.0.2 + which-boxed-primitive: 1.0.2 + dev: true + + /union-value/1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + + /unique-filename/1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + dependencies: + unique-slug: 2.0.2 + dev: false + + /unique-slug/2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + dependencies: + imurmurhash: 0.1.4 + dev: false + + /universalify/0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + /universalify/2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: false + + /unset-value/1.0.0: + resolution: {integrity: sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + /upper-case-first/1.1.2: + resolution: {integrity: sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=} + dependencies: + upper-case: 1.1.3 + dev: false + + /upper-case/1.1.3: + resolution: {integrity: sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=} + dev: false + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /urix/0.1.0: + resolution: {integrity: sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=} + deprecated: Please see https://github.com/lydell/urix#deprecated + + /use/3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /uuid/3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: true + + /v8-compile-cache/2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: true + + /v8-to-istanbul/4.1.4: + resolution: {integrity: sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==} + engines: {node: 8.x.x || >=10.10.0} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + convert-source-map: 1.8.0 + source-map: 0.7.3 + dev: true + + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + dev: true + + /validate-npm-package-name/3.0.0: + resolution: {integrity: sha1-X6kS2B630MdK/BQN5zF/DKffQ34=} + dependencies: + builtins: 1.0.3 + dev: false + + /validator/13.7.0: + resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} + engines: {node: '>= 0.10'} + + /validator/8.2.0: + resolution: {integrity: sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==} + engines: {node: '>= 0.10'} + + /verror/1.10.0: + resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + + /w3c-hr-time/1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + dependencies: + browser-process-hrtime: 1.0.0 + dev: true + + /w3c-xmlserializer/1.1.2: + resolution: {integrity: sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==} + dependencies: + domexception: 1.0.1 + webidl-conversions: 4.0.2 + xml-name-validator: 3.0.0 + dev: true + + /walker/1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /warning-symbol/0.1.0: + resolution: {integrity: sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE=} + engines: {node: '>=0.10.0'} + dev: false + + /wcwidth/1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.3 + dev: false + + /webidl-conversions/4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /whatwg-encoding/1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + dependencies: + iconv-lite: 0.4.24 + dev: true + + /whatwg-mimetype/2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + dev: true + + /whatwg-url/7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + + /which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.6 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-module/2.0.0: + resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} + dev: true + + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /wide-align/1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false + + /word-wrap/1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /wordwrap/0.0.3: + resolution: {integrity: sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==} + engines: {node: '>=0.4.0'} + dev: false + + /wordwrap/1.0.0: + resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=} + dev: false + + /wrap-ansi/6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + /wrap-ansi/7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /write-file-atomic/3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.6 + typedarray-to-buffer: 3.1.5 + dev: true + + /ws/7.5.6: + resolution: {integrity: sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /x256/0.0.2: + resolution: {integrity: sha512-ZsIH+sheoF8YG9YG+QKEEIdtqpHRA9FYuD7MqhfyB1kayXU43RUNBFSxBEnF8ywSUxdg+8no4+bPr5qLbyxKgA==} + engines: {node: '>=0.4.0'} + dev: false + + /xml-name-validator/3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + dev: true + + /xml2js/0.4.23: + resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 + dev: false + + /xmlbuilder/11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + dev: false + + /xmlchars/2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: false + + /y18n/4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n/5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + + /yargs-parser/18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser/21.0.0: + resolution: {integrity: sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==} + engines: {node: '>=12'} + dev: false + + /yargs/15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.0 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /yargs/17.3.0: + resolution: {integrity: sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.0.0 + dev: false + + /year/0.2.1: + resolution: {integrity: sha1-QIOuUgoxiyPshgN/MADLiSvfm7A=} + engines: {node: '>=0.8'} + dev: false + + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: false + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: false + + /z-schema/3.18.4: + resolution: {integrity: sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 8.2.0 + optionalDependencies: + commander: 2.20.3 + + /z-schema/5.0.2: + resolution: {integrity: sha512-40TH47ukMHq5HrzkeVE40Ad7eIDKaRV2b+Qpi2prLc9X9eFJFzV7tMe5aH12e6avaSS/u5l653EQOv+J9PirPw==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.7.0 + optionalDependencies: + commander: 2.20.3 diff --git a/common/config/rush/repo-state.json b/common/config/rush/repo-state.json new file mode 100644 index 0000000..0e7b144 --- /dev/null +++ b/common/config/rush/repo-state.json @@ -0,0 +1,4 @@ +// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. +{ + "preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f" +} diff --git a/common/config/rush/rush-plugins.json b/common/config/rush/rush-plugins.json new file mode 100644 index 0000000..b4d5c7e --- /dev/null +++ b/common/config/rush/rush-plugins.json @@ -0,0 +1,55 @@ +/** + * This configuration file manages Rush's plugin feature. + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugins.schema.json", + "plugins": [ + /** + * Each item defines a plugin configuration used by Rush. + */ + // { + // /** + // * The name of the rush plugin package. + // */ + // "packageName": "@scope/my-rush-plugin", + // /** + // * The name of the plugin provided by rush plugin package + // */ + // "pluginName": "my-plugin-name", + // /** + // * Autoinstaller name used to install the plugin. + // */ + // "autoinstallerName": "plugins" + // } + { + "packageName": "rush-init-project-plugin", + "pluginName": "rush-init-project-plugin", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + }, + { + "packageName": "rush-archive-project-plugin", + "pluginName": "rush-archive-project-plugin", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + }, + { + "packageName": "rush-audit-cache-plugin", + "pluginName": "rush-audit-cache-plugin", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + }, + { + "packageName": "rush-lint-staged-plugin", + "pluginName": "rush-lint-staged-plugin", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + }, + { + "packageName": "rush-sort-package-json", + "pluginName": "rush-sort-package-json", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + }, + { + "packageName": "rush-upgrade-self-plugin", + "pluginName": "rush-upgrade-self-plugin", + "autoinstallerName": "command-plugins" // the name of autoinstaller you created before + } + ] +} diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json new file mode 100644 index 0000000..048aef0 --- /dev/null +++ b/common/config/rush/version-policies.json @@ -0,0 +1,102 @@ +/** + * This is configuration file is used for advanced publishing configurations with Rush. + * More documentation is available on the Rush website: https://rushjs.io + */ + +/** + * A list of version policy definitions. A "version policy" is a custom package versioning + * strategy that affects "rush change", "rush version", and "rush publish". The strategy applies + * to a set of projects that are specified using the "versionPolicyName" field in rush.json. + */ +[ + // { + // /** + // * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion"). + // * + // * The "lockStepVersion" mode specifies that the projects will use "lock-step versioning". This + // * strategy is appropriate for a set of packages that act as selectable components of a + // * unified product. The entire set of packages are always published together, and always share + // * the same NPM version number. When the packages depend on other packages in the set, the + // * SemVer range is usually restricted to a single version. + // */ + // "definitionName": "lockStepVersion", + // + // /** + // * (Required) The name that will be used for the "versionPolicyName" field in rush.json. + // * This name is also used command-line parameters such as "--version-policy" + // * and "--to-version-policy". + // */ + // "policyName": "MyBigFramework", + // + // /** + // * (Required) The current version. All packages belonging to the set should have this version + // * in the current branch. When bumping versions, Rush uses this to determine the next version. + // * (The "version" field in package.json is NOT considered.) + // */ + // "version": "1.0.0", + // + // /** + // * (Required) The type of bump that will be performed when publishing the next release. + // * When creating a release branch in Git, this field should be updated according to the + // * type of release. + // * + // * Valid values are: "prerelease", "release", "minor", "patch", "major" + // */ + // "nextBump": "prerelease", + // + // /** + // * (Optional) If specified, all packages in the set share a common CHANGELOG.md file. + // * This file is stored with the specified "main" project, which must be a member of the set. + // * + // * If this field is omitted, then a separate CHANGELOG.md file will be maintained for each + // * package in the set. + // */ + // "mainProject": "my-app", + // + // /** + // * (Optional) If enabled, the "rush change" command will prompt the user for their email address + // * and include it in the JSON change files. If an organization maintains multiple repos, tracking + // * this contact information may be useful for a service that automatically upgrades packages and + // * needs to notify engineers whose change may be responsible for a downstream build break. It might + // * also be useful for crediting contributors. Rush itself does not do anything with the collected + // * email addresses. The default value is "false". + // */ + // // "includeEmailInChangeFile": true + // }, + // + // { + // /** + // * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion"). + // * + // * The "individualVersion" mode specifies that the projects will use "individual versioning". + // * This is the typical NPM model where each package has an independent version number + // * and CHANGELOG.md file. Although a single CI definition is responsible for publishing the + // * packages, they otherwise don't have any special relationship. The version bumping will + // * depend on how developers answer the "rush change" questions for each package that + // * is changed. + // */ + // "definitionName": "individualVersion", + // + // "policyName": "MyRandomLibraries", + // + // /** + // * (Optional) This can be used to enforce that all packages in the set must share a common + // * major version number, e.g. because they are from the same major release branch. + // * It can also be used to discourage people from accidentally making "MAJOR" SemVer changes + // * inappropriately. The minor/patch version parts will be bumped independently according + // * to the types of changes made to each project, according to the "rush change" command. + // */ + // "lockedMajor": 3, + // + // /** + // * (Optional) When publishing is managed by Rush, by default the "rush change" command will + // * request changes for any projects that are modified by a pull request. These change entries + // * will produce a CHANGELOG.md file. If you author your CHANGELOG.md manually or announce updates + // * in some other way, set "exemptFromRushChange" to true to tell "rush change" to ignore the projects + // * belonging to this version policy. + // */ + // "exemptFromRushChange": false, + // + // // "includeEmailInChangeFile": true + // } +] diff --git a/common/git-hooks/commit-msg.sample b/common/git-hooks/commit-msg.sample new file mode 100644 index 0000000..e24e365 --- /dev/null +++ b/common/git-hooks/commit-msg.sample @@ -0,0 +1,25 @@ +#!/bin/sh +# +# This is an example Git hook for use with Rush. To enable this hook, rename this file +# to "commit-msg" and then run "rush install", which will copy it from common/git-hooks +# to the .git/hooks folder. +# +# TO LEARN MORE ABOUT GIT HOOKS +# +# The Git documentation is here: https://git-scm.com/docs/githooks +# Some helpful resources: https://githooks.com +# +# ABOUT THIS EXAMPLE +# +# The commit-msg hook is called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero status after issuing +# an appropriate message if it wants to stop the commit. The hook is allowed to edit +# the commit message file. + +# This example enforces that commit message should contain a minimum amount of +# description text. +if [ `cat $1 | wc -w` -lt 3 ]; then + echo "" + echo "Invalid commit message: The message must contain at least 3 words." + exit 1 +fi diff --git a/common/git-hooks/pre-commit b/common/git-hooks/pre-commit new file mode 100644 index 0000000..e478254 --- /dev/null +++ b/common/git-hooks/pre-commit @@ -0,0 +1,12 @@ +#!/bin/sh + +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. + +# Invoke the "rush prettier" custom command to reformat files whenever they +# are committed. The command is defined in common/config/rush/command-line.json +# and uses the "rush-prettier" autoinstaller. +node common/scripts/install-run-rush.js --quiet prettier || exit $? + +node common/scripts/install-run-rush.js --quiet lint-staged || exit $? \ No newline at end of file diff --git a/common/scripts/install-run-rush.js b/common/scripts/install-run-rush.js new file mode 100644 index 0000000..1639efd --- /dev/null +++ b/common/scripts/install-run-rush.js @@ -0,0 +1,116 @@ +"use strict"; +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. +// +// This script is intended for usage in an automated build environment where the Rush command may not have +// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush +// specified in the rush.json configuration file (if not already installed), and then pass a command-line to it. +// An example usage would be: +// +// node common/scripts/install-run-rush.js install +// +// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +const path = __importStar(require("path")); +const fs = __importStar(require("fs")); +const install_run_1 = require("./install-run"); +const PACKAGE_NAME = '@microsoft/rush'; +const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; +const INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_RUSH_LOCKFILE_PATH'; +function _getRushVersion(logger) { + const rushPreviewVersion = process.env[RUSH_PREVIEW_VERSION]; + if (rushPreviewVersion !== undefined) { + logger.info(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`); + return rushPreviewVersion; + } + const rushJsonFolder = (0, install_run_1.findRushJsonFolder)(); + const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME); + try { + const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8'); + // Use a regular expression to parse out the rushVersion value because rush.json supports comments, + // but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script. + const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/); + return rushJsonMatches[1]; + } + catch (e) { + throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + + "The 'rushVersion' field is either not assigned in rush.json or was specified " + + 'using an unexpected syntax.'); + } +} +function _run() { + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv; + // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the + // appropriate binary inside the rush package to run + const scriptName = path.basename(scriptPath); + const bin = scriptName.toLowerCase() === 'install-run-rushx.js' ? 'rushx' : 'rush'; + if (!nodePath || !scriptPath) { + throw new Error('Unexpected exception: could not detect node path or script path'); + } + let commandFound = false; + let logger = { info: console.log, error: console.error }; + for (const arg of packageBinArgs) { + if (arg === '-q' || arg === '--quiet') { + // The -q/--quiet flag is supported by both `rush` and `rushx`, and will suppress + // any normal informational/diagnostic information printed during startup. + // + // To maintain the same user experience, the install-run* scripts pass along this + // flag but also use it to suppress any diagnostic information normally printed + // to stdout. + logger = { + info: () => { }, + error: console.error + }; + } + else if (!arg.startsWith('-') || arg === '-h' || arg === '--help') { + // We either found something that looks like a command (i.e. - doesn't start with a "-"), + // or we found the -h/--help flag, which can be run without a command + commandFound = true; + } + } + if (!commandFound) { + console.log(`Usage: ${scriptName} [args...]`); + if (scriptName === 'install-run-rush.js') { + console.log(`Example: ${scriptName} build --to myproject`); + } + else { + console.log(`Example: ${scriptName} custom-command`); + } + process.exit(1); + } + (0, install_run_1.runWithErrorAndStatusCode)(logger, () => { + const version = _getRushVersion(logger); + logger.info(`The rush.json configuration requests Rush version ${version}`); + const lockFilePath = process.env[INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE]; + if (lockFilePath) { + logger.info(`Found ${INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE}="${lockFilePath}", installing with lockfile.`); + } + return (0, install_run_1.installAndRun)(logger, PACKAGE_NAME, version, bin, packageBinArgs, lockFilePath); + }); +} +_run(); +//# sourceMappingURL=install-run-rush.js.map \ No newline at end of file diff --git a/common/scripts/install-run-rushx.js b/common/scripts/install-run-rushx.js new file mode 100644 index 0000000..bf26eb5 --- /dev/null +++ b/common/scripts/install-run-rushx.js @@ -0,0 +1,18 @@ +"use strict"; +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for license information. +Object.defineProperty(exports, "__esModule", { value: true }); +// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. +// +// This script is intended for usage in an automated build environment where the Rush command may not have +// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush +// specified in the rush.json configuration file (if not already installed), and then pass a command-line to the +// rushx command. +// +// An example usage would be: +// +// node common/scripts/install-run-rushx.js custom-command +// +// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +require("./install-run-rush"); +//# sourceMappingURL=install-run-rushx.js.map \ No newline at end of file diff --git a/common/scripts/install-run.js b/common/scripts/install-run.js new file mode 100644 index 0000000..948da06 --- /dev/null +++ b/common/scripts/install-run.js @@ -0,0 +1,500 @@ +"use strict"; +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.runWithErrorAndStatusCode = exports.installAndRun = exports.findRushJsonFolder = exports.getNpmPath = exports.RUSH_JSON_FILENAME = void 0; +// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. +// +// This script is intended for usage in an automated build environment where a Node tool may not have +// been preinstalled, or may have an unpredictable version. This script will automatically install the specified +// version of the specified tool (if not already installed), and then pass a command-line to it. +// An example usage would be: +// +// node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io +// +// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +const childProcess = __importStar(require("child_process")); +const fs = __importStar(require("fs")); +const os = __importStar(require("os")); +const path = __importStar(require("path")); +exports.RUSH_JSON_FILENAME = 'rush.json'; +const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; +const INSTALL_RUN_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_LOCKFILE_PATH'; +const INSTALLED_FLAG_FILENAME = 'installed.flag'; +const NODE_MODULES_FOLDER_NAME = 'node_modules'; +const PACKAGE_JSON_FILENAME = 'package.json'; +/** + * Parse a package specifier (in the form of name\@version) into name and version parts. + */ +function _parsePackageSpecifier(rawPackageSpecifier) { + rawPackageSpecifier = (rawPackageSpecifier || '').trim(); + const separatorIndex = rawPackageSpecifier.lastIndexOf('@'); + let name; + let version = undefined; + if (separatorIndex === 0) { + // The specifier starts with a scope and doesn't have a version specified + name = rawPackageSpecifier; + } + else if (separatorIndex === -1) { + // The specifier doesn't have a version + name = rawPackageSpecifier; + } + else { + name = rawPackageSpecifier.substring(0, separatorIndex); + version = rawPackageSpecifier.substring(separatorIndex + 1); + } + if (!name) { + throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`); + } + return { name, version }; +} +/** + * As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims + * unusable lines from the .npmrc file. + * + * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in + * the .npmrc file to provide different authentication tokens for different registry. + * However, if the environment variable is undefined, it expands to an empty string, which + * produces a valid-looking mapping with an invalid URL that causes an error. Instead, + * we'd prefer to skip that line and continue looking in other places such as the user's + * home directory. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities.copyAndTrimNpmrcFile() + */ +function _copyAndTrimNpmrcFile(logger, sourceNpmrcPath, targetNpmrcPath) { + logger.info(`Transforming ${sourceNpmrcPath}`); // Verbose + logger.info(` --> "${targetNpmrcPath}"`); + let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); + npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); + const resultLines = []; + // This finds environment variable tokens that look like "${VAR_NAME}" + const expansionRegExp = /\$\{([^\}]+)\}/g; + // Comment lines start with "#" or ";" + const commentRegExp = /^\s*[#;]/; + // Trim out lines that reference environment variables that aren't defined + for (const line of npmrcFileLines) { + let lineShouldBeTrimmed = false; + // Ignore comment lines + if (!commentRegExp.test(line)) { + const environmentVariables = line.match(expansionRegExp); + if (environmentVariables) { + for (const token of environmentVariables) { + // Remove the leading "${" and the trailing "}" from the token + const environmentVariableName = token.substring(2, token.length - 1); + // Is the environment variable defined? + if (!process.env[environmentVariableName]) { + // No, so trim this line + lineShouldBeTrimmed = true; + break; + } + } + } + } + if (lineShouldBeTrimmed) { + // Example output: + // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" + resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); + } + else { + resultLines.push(line); + } + } + fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); +} +/** + * syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file. + * If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() + */ +function _syncNpmrc(logger, sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish) { + const sourceNpmrcPath = path.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); + const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); + try { + if (fs.existsSync(sourceNpmrcPath)) { + _copyAndTrimNpmrcFile(logger, sourceNpmrcPath, targetNpmrcPath); + } + else if (fs.existsSync(targetNpmrcPath)) { + // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target + logger.info(`Deleting ${targetNpmrcPath}`); // Verbose + fs.unlinkSync(targetNpmrcPath); + } + } + catch (e) { + throw new Error(`Error syncing .npmrc file: ${e}`); + } +} +let _npmPath = undefined; +/** + * Get the absolute path to the npm executable + */ +function getNpmPath() { + if (!_npmPath) { + try { + if (os.platform() === 'win32') { + // We're on Windows + const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); + const lines = whereOutput.split(os.EOL).filter((line) => !!line); + // take the last result, we are looking for a .cmd command + // see https://github.com/microsoft/rushstack/issues/759 + _npmPath = lines[lines.length - 1]; + } + else { + // We aren't on Windows - assume we're on *NIX or Darwin + _npmPath = childProcess.execSync('command -v npm', { stdio: [] }).toString(); + } + } + catch (e) { + throw new Error(`Unable to determine the path to the NPM tool: ${e}`); + } + _npmPath = _npmPath.trim(); + if (!fs.existsSync(_npmPath)) { + throw new Error('The NPM executable does not exist'); + } + } + return _npmPath; +} +exports.getNpmPath = getNpmPath; +function _ensureFolder(folderPath) { + if (!fs.existsSync(folderPath)) { + const parentDir = path.dirname(folderPath); + _ensureFolder(parentDir); + fs.mkdirSync(folderPath); + } +} +/** + * Create missing directories under the specified base directory, and return the resolved directory. + * + * Does not support "." or ".." path segments. + * Assumes the baseFolder exists. + */ +function _ensureAndJoinPath(baseFolder, ...pathSegments) { + let joinedPath = baseFolder; + try { + for (let pathSegment of pathSegments) { + pathSegment = pathSegment.replace(/[\\\/]/g, '+'); + joinedPath = path.join(joinedPath, pathSegment); + if (!fs.existsSync(joinedPath)) { + fs.mkdirSync(joinedPath); + } + } + } + catch (e) { + throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); + } + return joinedPath; +} +function _getRushTempFolder(rushCommonFolder) { + const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; + if (rushTempFolder !== undefined) { + _ensureFolder(rushTempFolder); + return rushTempFolder; + } + else { + return _ensureAndJoinPath(rushCommonFolder, 'temp'); + } +} +/** + * Resolve a package specifier to a static version + */ +function _resolvePackageVersion(logger, rushCommonFolder, { name, version }) { + if (!version) { + version = '*'; // If no version is specified, use the latest version + } + if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) { + // If the version contains only characters that we recognize to be used in static version specifiers, + // pass the version through + return version; + } + else { + // version resolves to + try { + const rushTempFolder = _getRushTempFolder(rushCommonFolder); + const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); + _syncNpmrc(logger, sourceNpmrcFolder, rushTempFolder); + const npmPath = getNpmPath(); + // This returns something that looks like: + // @microsoft/rush@3.0.0 '3.0.0' + // @microsoft/rush@3.0.1 '3.0.1' + // ... + // @microsoft/rush@3.0.20 '3.0.20' + // + const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], { + cwd: rushTempFolder, + stdio: [] + }); + if (npmVersionSpawnResult.status !== 0) { + throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`); + } + const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString(); + const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line); + const latestVersion = versionLines[versionLines.length - 1]; + if (!latestVersion) { + throw new Error('No versions found for the specified version range.'); + } + const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/); + if (!versionMatches) { + throw new Error(`Invalid npm output ${latestVersion}`); + } + return versionMatches[1]; + } + catch (e) { + throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`); + } + } +} +let _rushJsonFolder; +/** + * Find the absolute path to the folder containing rush.json + */ +function findRushJsonFolder() { + if (!_rushJsonFolder) { + let basePath = __dirname; + let tempPath = __dirname; + do { + const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME); + if (fs.existsSync(testRushJsonPath)) { + _rushJsonFolder = basePath; + break; + } + else { + basePath = tempPath; + } + } while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root + if (!_rushJsonFolder) { + throw new Error('Unable to find rush.json.'); + } + } + return _rushJsonFolder; +} +exports.findRushJsonFolder = findRushJsonFolder; +/** + * Detects if the package in the specified directory is installed + */ +function _isPackageAlreadyInstalled(packageInstallFolder) { + try { + const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); + if (!fs.existsSync(flagFilePath)) { + return false; + } + const fileContents = fs.readFileSync(flagFilePath).toString(); + return fileContents.trim() === process.version; + } + catch (e) { + return false; + } +} +/** + * Delete a file. Fail silently if it does not exist. + */ +function _deleteFile(file) { + try { + fs.unlinkSync(file); + } + catch (err) { + if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') { + throw err; + } + } +} +/** + * Removes the following files and directories under the specified folder path: + * - installed.flag + * - + * - node_modules + */ +function _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath) { + try { + const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME); + _deleteFile(flagFile); + const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json'); + if (lockFilePath) { + fs.copyFileSync(lockFilePath, packageLockFile); + } + else { + // Not running `npm ci`, so need to cleanup + _deleteFile(packageLockFile); + const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); + if (fs.existsSync(nodeModulesFolder)) { + const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler'); + fs.renameSync(nodeModulesFolder, path.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`)); + } + } + } + catch (e) { + throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`); + } +} +function _createPackageJson(packageInstallFolder, name, version) { + try { + const packageJsonContents = { + name: 'ci-rush', + version: '0.0.0', + dependencies: { + [name]: version + }, + description: "DON'T WARN", + repository: "DON'T WARN", + license: 'MIT' + }; + const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME); + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); + } + catch (e) { + throw new Error(`Unable to create package.json: ${e}`); + } +} +/** + * Run "npm install" in the package install folder. + */ +function _installPackage(logger, packageInstallFolder, name, version, command) { + try { + logger.info(`Installing ${name}...`); + const npmPath = getNpmPath(); + const result = childProcess.spawnSync(npmPath, [command], { + stdio: 'inherit', + cwd: packageInstallFolder, + env: process.env + }); + if (result.status !== 0) { + throw new Error(`"npm ${command}" encountered an error`); + } + logger.info(`Successfully installed ${name}@${version}`); + } + catch (e) { + throw new Error(`Unable to install package: ${e}`); + } +} +/** + * Get the ".bin" path for the package. + */ +function _getBinPath(packageInstallFolder, binName) { + const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + const resolvedBinName = os.platform() === 'win32' ? `${binName}.cmd` : binName; + return path.resolve(binFolderPath, resolvedBinName); +} +/** + * Write a flag file to the package's install directory, signifying that the install was successful. + */ +function _writeFlagFile(packageInstallFolder) { + try { + const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); + fs.writeFileSync(flagFilePath, process.version); + } + catch (e) { + throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`); + } +} +function installAndRun(logger, packageName, packageVersion, packageBinName, packageBinArgs, lockFilePath = process.env[INSTALL_RUN_LOCKFILE_PATH_VARIABLE]) { + const rushJsonFolder = findRushJsonFolder(); + const rushCommonFolder = path.join(rushJsonFolder, 'common'); + const rushTempFolder = _getRushTempFolder(rushCommonFolder); + const packageInstallFolder = _ensureAndJoinPath(rushTempFolder, 'install-run', `${packageName}@${packageVersion}`); + if (!_isPackageAlreadyInstalled(packageInstallFolder)) { + // The package isn't already installed + _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath); + const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); + _syncNpmrc(logger, sourceNpmrcFolder, packageInstallFolder); + _createPackageJson(packageInstallFolder, packageName, packageVersion); + const command = lockFilePath ? 'ci' : 'install'; + _installPackage(logger, packageInstallFolder, packageName, packageVersion, command); + _writeFlagFile(packageInstallFolder); + } + const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`; + const statusMessageLine = new Array(statusMessage.length + 1).join('-'); + logger.info(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL); + const binPath = _getBinPath(packageInstallFolder, packageBinName); + const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + // Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to + // assign via the process.env proxy to ensure that we append to the right PATH key. + const originalEnvPath = process.env.PATH || ''; + let result; + try { + // Node.js on Windows can not spawn a file when the path has a space on it + // unless the path gets wrapped in a cmd friendly way and shell mode is used + const shouldUseShell = binPath.includes(' ') && os.platform() === 'win32'; + const platformBinPath = shouldUseShell ? `"${binPath}"` : binPath; + process.env.PATH = [binFolderPath, originalEnvPath].join(path.delimiter); + result = childProcess.spawnSync(platformBinPath, packageBinArgs, { + stdio: 'inherit', + windowsVerbatimArguments: false, + shell: shouldUseShell, + cwd: process.cwd(), + env: process.env + }); + } + finally { + process.env.PATH = originalEnvPath; + } + if (result.status !== null) { + return result.status; + } + else { + throw result.error || new Error('An unknown error occurred.'); + } +} +exports.installAndRun = installAndRun; +function runWithErrorAndStatusCode(logger, fn) { + process.exitCode = 1; + try { + const exitCode = fn(); + process.exitCode = exitCode; + } + catch (e) { + logger.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL); + } +} +exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode; +function _run() { + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; + if (!nodePath) { + throw new Error('Unexpected exception: could not detect node path'); + } + if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') { + // If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control + // to the script that (presumably) imported this file + return; + } + if (process.argv.length < 4) { + console.log('Usage: install-run.js @ [args...]'); + console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io'); + process.exit(1); + } + const logger = { info: console.log, error: console.error }; + runWithErrorAndStatusCode(logger, () => { + const rushJsonFolder = findRushJsonFolder(); + const rushCommonFolder = _ensureAndJoinPath(rushJsonFolder, 'common'); + const packageSpecifier = _parsePackageSpecifier(rawPackageSpecifier); + const name = packageSpecifier.name; + const version = _resolvePackageVersion(logger, rushCommonFolder, packageSpecifier); + if (packageSpecifier.version !== version) { + console.log(`Resolved to ${name}@${version}`); + } + return installAndRun(logger, name, version, packageBinName, packageBinArgs); + }); +} +_run(); +//# sourceMappingURL=install-run.js.map \ No newline at end of file diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..a5b905d --- /dev/null +++ b/cspell.json @@ -0,0 +1,21 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": [ + "buildable", + "lilconfig", + "nonbrowser", + "noreply", + "npmjs", + "npmrc", + "packument", + "pacote", + "plopfile", + "subfolders", + "unshift" + ], + "ignoreWords": [], + "import": [] +} diff --git a/lint-staged.config.cjs b/lint-staged.config.cjs new file mode 100644 index 0000000..6334aee --- /dev/null +++ b/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*": "echo 'good job'", +}; +module.exports = config; diff --git a/rush-plugins/rush-archive-project-plugin/.eslintrc.js b/rush-plugins/rush-archive-project-plugin/.eslintrc.js new file mode 100644 index 0000000..0b39739 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/", "**/test/**"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-archive-project-plugin/.gitignore b/rush-plugins/rush-archive-project-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-archive-project-plugin/.npmignore b/rush-plugins/rush-archive-project-plugin/.npmignore new file mode 100644 index 0000000..759c0d3 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/.npmignore @@ -0,0 +1,36 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js +/lib/__mocks__/ +/src/__mocks__/ + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-archive-project-plugin/CHANGELOG.json b/rush-plugins/rush-archive-project-plugin/CHANGELOG.json new file mode 100644 index 0000000..5e0ef36 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/CHANGELOG.json @@ -0,0 +1,151 @@ +{ + "name": "rush-archive-project-plugin", + "entries": [ + { + "version": "1.1.7", + "tag": "rush-archive-project-plugin_v1.1.7", + "date": "Wed, 18 Jan 2023 06:59:28 GMT", + "comments": { + "patch": [ + { + "comment": "Add support for graveyard folder in archive plugin config file" + } + ] + } + }, + { + "version": "1.1.6", + "tag": "rush-archive-project-plugin_v1.1.6", + "date": "Mon, 16 Jan 2023 05:03:53 GMT", + "comments": { + "patch": [ + { + "comment": "Add ability to push git branch and generate md file for archived projects\"" + } + ] + } + }, + { + "version": "1.1.5", + "tag": "rush-archive-project-plugin_v1.1.5", + "date": "Sat, 07 Jan 2023 01:07:03 GMT", + "comments": { + "patch": [ + { + "comment": "Updated to include a git checkpoint branch when archiving a project" + }, + { + "comment": "Update README for archive plugin and add unarchiving support" + } + ] + } + }, + { + "version": "1.1.4", + "tag": "rush-archive-project-plugin_v1.1.4", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + }, + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "1.1.3", + "tag": "rush-archive-project-plugin_v1.1.3", + "date": "Thu, 24 Feb 2022 11:57:31 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade rush-sdk to latest" + } + ] + } + }, + { + "version": "1.1.2", + "tag": "rush-archive-project-plugin_v1.1.2", + "date": "Thu, 24 Feb 2022 10:57:56 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade rush-sdk to latest" + } + ] + } + }, + { + "version": "1.1.1", + "tag": "rush-archive-project-plugin_v1.1.1", + "date": "Tue, 14 Dec 2021 15:40:43 GMT", + "comments": { + "patch": [ + { + "comment": "Fix rush configuration cache" + } + ] + } + }, + { + "version": "1.1.0", + "tag": "rush-archive-project-plugin_v1.1.0", + "date": "Tue, 14 Dec 2021 15:22:03 GMT", + "comments": { + "minor": [ + { + "comment": "Prompt user to run rush update after archive" + }, + { + "comment": "Assert no consuming projects when archive" + } + ] + } + }, + { + "version": "1.0.1", + "tag": "rush-archive-project-plugin_v1.0.1", + "date": "Mon, 13 Dec 2021 00:58:24 GMT", + "comments": { + "patch": [ + { + "comment": "update readme" + } + ] + } + }, + { + "version": "1.0.0", + "tag": "rush-archive-project-plugin_v1.0.0", + "date": "Sun, 12 Dec 2021 14:59:51 GMT", + "comments": { + "patch": [ + { + "comment": "update readme" + } + ], + "major": [ + { + "comment": "improve cli logging" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-archive-project-plugin_v0.1.0", + "date": "Sun, 12 Dec 2021 14:29:03 GMT", + "comments": { + "minor": [ + { + "comment": "unarchive first implementation" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/CHANGELOG.md b/rush-plugins/rush-archive-project-plugin/CHANGELOG.md new file mode 100644 index 0000000..df24fec --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/CHANGELOG.md @@ -0,0 +1,88 @@ +# Change Log - rush-archive-project-plugin + +This log was last generated on Wed, 18 Jan 2023 06:59:28 GMT and should not be manually modified. + +## 1.1.7 +Wed, 18 Jan 2023 06:59:28 GMT + +### Patches + +- Add support for graveyard folder in archive plugin config file + +## 1.1.6 +Mon, 16 Jan 2023 05:03:53 GMT + +### Patches + +- Add ability to push git branch and generate md file for archived projects" + +## 1.1.5 +Sat, 07 Jan 2023 01:07:03 GMT + +### Patches + +- Updated to include a git checkpoint branch when archiving a project +- Update README for archive plugin and add unarchiving support + +## 1.1.4 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme +- Update readme + +## 1.1.3 +Thu, 24 Feb 2022 11:57:31 GMT + +### Patches + +- Upgrade rush-sdk to latest + +## 1.1.2 +Thu, 24 Feb 2022 10:57:56 GMT + +### Patches + +- Upgrade rush-sdk to latest + +## 1.1.1 +Tue, 14 Dec 2021 15:40:43 GMT + +### Patches + +- Fix rush configuration cache + +## 1.1.0 +Tue, 14 Dec 2021 15:22:03 GMT + +### Minor changes + +- Prompt user to run rush update after archive +- Assert no consuming projects when archive + +## 1.0.1 +Mon, 13 Dec 2021 00:58:24 GMT + +### Patches + +- update readme + +## 1.0.0 +Sun, 12 Dec 2021 14:59:51 GMT + +### Breaking changes + +- improve cli logging + +### Patches + +- update readme + +## 0.1.0 +Sun, 12 Dec 2021 14:29:03 GMT + +### Minor changes + +- unarchive first implementation + diff --git a/rush-plugins/rush-archive-project-plugin/LICENSE b/rush-plugins/rush-archive-project-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-archive-project-plugin/README.md b/rush-plugins/rush-archive-project-plugin/README.md new file mode 100644 index 0000000..d7691cd --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/README.md @@ -0,0 +1,45 @@ +# rush-archive-project-plugin + +A rush plugin for archive/unarchive project source code in monorepo. + +# Prerequisite + +Rush.js >= 5.57.0 + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + + +2. Running archive project command + +``` +rush archive-project --package-name +``` + +> restoring your code by `rush unarchive-project --package-name ` + +# Archive working process + +1. Find project configuration by Rush.js SDK +2. Check whether there are projects depends on target project +3. Run `git clean -xdf` under project folder +4. Create a checkpoint branch with the name `${projectName}-checkpoint-${date}` +5. Update checkpoint branch information in `common/_graveyard/projectCheckpoints.json` file +6. Record project configuration into `rush-metadata.json` file +7. Create a tarball by running `tar -czf .tar.gz -C .` +8. Move the tarball to `common/_graveyard` folder +9. Remove project config to `rush.json` +10. Delete project folder + +# Unarchive working process + +1. Find the tarball by `packageName` +2. Extract the tarball by running `tar xf .tar.gz` +3. Get project configuration by reading `rush-metadata.json` +4. Remove checkpoint branch information from checkpoint metadata file if it exists +5. Move the code to project folder +6. Restore project configuration into `rush.json` +7. Delete metadata file and tarball diff --git a/rush-plugins/rush-archive-project-plugin/command-line.json b/rush-plugins/rush-archive-project-plugin/command-line.json new file mode 100644 index 0000000..41555bb --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/command-line.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "archive-project", + "commandKind": "global", + "summary": "Archives the project to a tar file", + "shellCommand": "rush-project-archiver archive", + "safeForSimultaneousRushProcesses": true + }, + { + "name": "unarchive-project", + "commandKind": "global", + "summary": "Unarchive the project from a tar file", + "shellCommand": "rush-project-archiver unarchive", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "description": "The name of the package", + "longName": "--package-name", + "argumentName": "PACKAGE_NAME", + "associatedCommands": ["archive-project", "unarchive-project"], + "required": true + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/config/heft.json b/rush-plugins/rush-archive-project-plugin/config/heft.json new file mode 100644 index 0000000..6b75c55 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/config/heft.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ], + + "heftPlugins": [{ "plugin": "@rushstack/heft-jest-plugin" }] +} diff --git a/rush-plugins/rush-archive-project-plugin/config/jest.config.json b/rush-plugins/rush-archive-project-plugin/config/jest.config.json new file mode 100644 index 0000000..b6f305e --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/config/jest.config.json @@ -0,0 +1,3 @@ +{ + "extends": "@rushstack/heft-jest-plugin/includes/jest-shared.config.json" +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/demo/package.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/demo/package.json new file mode 100644 index 0000000..f793675 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/demo/package.json @@ -0,0 +1,4 @@ +{ + "name": "demo-project", + "version": "0.0.1" +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/rush.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/rush.json new file mode 100644 index 0000000..1a96d9a --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-1/rush.json @@ -0,0 +1,16 @@ +{ + "rushVersion": "5.57.1", + "pnpmVersion": "6.23.1", + "pnpmOptions": { + "useWorkspaces": true + }, + "projects": [ + { + "packageName": "demo-project", + "projectFolder": "demo", + "reviewCategory": "lib", + "cyclicDependencyProjects": [], + "shouldPublish": false + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-2/common/_graveyard/demo-project.tar.gz b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-2/common/_graveyard/demo-project.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..98fcc5e6883a55379fadb21380990fc92d4211fd GIT binary patch literal 345 zcmV-f0jB;RiwFP!000006YZ7HYr-%T$9pdLKZKrVO}eCoT^&0P?_-D9J~ggwBxxN* z{NI;a11fVKYT01dZi}o1tl*actSx2g&c2`Ttiv~4+m)rN())GDh_c-f|0); z`M;Erytb@wy8e!CowF5U4(<{2pKWJLvA0iRP|!BVQGRdX@7V%ns+NS|Q?Wd>#1%(|Df raeI3|`skIc^K4enbD>v8Snynfk@o)HZ6Jrk;poQ~1P}en01f~E6dLUAwDlg6K!BmgTfy7KS<)bbn^!>EtJv! zecCJ}9khE$!wU2B;E7)3?!MdwXJBy%AtmSVWLLcYIJe7wss&WlJS61g|N0MDD~@Bj_~02j!WJ^%m! literal 0 HcmV?d00001 diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/libraries/my-lib/package.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/libraries/my-lib/package.json new file mode 100644 index 0000000..59a32a5 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/libraries/my-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@my-company/my-lib", + "version": "0.0.1" +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/rush.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/rush.json new file mode 100644 index 0000000..adc9e4b --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-4/rush.json @@ -0,0 +1,28 @@ +/** + * This is the main configuration file for Rush. + * For full documentation, please see https://rushjs.io + */ +{ + /** + * (Required) This specifies the version of the Rush engine to be used in this repo. + * Rush's "version selector" feature ensures that the globally installed tool will + * behave like this release, regardless of which version is installed globally. + * + * The common/scripts/install-run-rush.js automation script also uses this version. + * + * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5" + * path segment in the "$schema" field for all your Rush config files. This will ensure + * correct error-underlining and tab-completion for editors such as VS Code. + */ + "rushVersion": "5.57.1", + "pnpmVersion": "6.23.1", + "pnpmOptions": { + "useWorkspaces": true + }, + "projects": [ + { + "packageName": "@my-company/my-lib", + "projectFolder": "libraries/my-lib" + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/apps/my-app/package.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/apps/my-app/package.json new file mode 100644 index 0000000..5344b07 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/apps/my-app/package.json @@ -0,0 +1,7 @@ +{ + "name": "@my-company/my-app", + "version": "0.0.1", + "dependencies": { + "@my-company/my-lib": "workspace:*" + } +} \ No newline at end of file diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/libraries/my-lib/package.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/libraries/my-lib/package.json new file mode 100644 index 0000000..59a32a5 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/libraries/my-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@my-company/my-lib", + "version": "0.0.1" +} diff --git a/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/rush.json b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/rush.json new file mode 100644 index 0000000..3e31875 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/fixtures/monorepo-5/rush.json @@ -0,0 +1,32 @@ +/** + * This is the main configuration file for Rush. + * For full documentation, please see https://rushjs.io + */ +{ + /** + * (Required) This specifies the version of the Rush engine to be used in this repo. + * Rush's "version selector" feature ensures that the globally installed tool will + * behave like this release, regardless of which version is installed globally. + * + * The common/scripts/install-run-rush.js automation script also uses this version. + * + * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5" + * path segment in the "$schema" field for all your Rush config files. This will ensure + * correct error-underlining and tab-completion for editors such as VS Code. + */ + "rushVersion": "5.57.1", + "pnpmVersion": "6.23.1", + "pnpmOptions": { + "useWorkspaces": true + }, + "projects": [ + { + "packageName": "@my-company/my-lib", + "projectFolder": "libraries/my-lib" + }, + { + "packageName": "@my-company/my-app", + "projectFolder": "apps/my-app" + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/lint-staged.config.cjs b/rush-plugins/rush-archive-project-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-archive-project-plugin/package.json b/rush-plugins/rush-archive-project-plugin/package.json new file mode 100644 index 0000000..550bdaf --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/package.json @@ -0,0 +1,55 @@ +{ + "name": "rush-archive-project-plugin", + "version": "1.1.7", + "description": "Rush plugin to archive project", + "keywords": [ + "rush", + "plugin", + "archive", + "project" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "bugs": { + "url": "https://github.com/tiktok/rush-plugins/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tiktok/rush-plugins.git", + "directory": "rush-plugins/rush-archive-project-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "bin": { + "rush-project-archiver": "lib/cli.js" + }, + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "inquirer": "~8.2.0", + "json2md": "~2.0.0", + "ora": "5.4.1", + "tar": "~6.1.11", + "yargs": "~17.3.0" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-jest-plugin": "~0.1.53", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/inquirer": "~8.1.3", + "@types/json2md": "~1.5.1", + "@types/node": "12.20.24", + "@types/pacote": "~11.1.1", + "@types/tar": "~6.1.1", + "@types/yargs": "~17.0.7", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json b/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..7f32f98 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-archive-project-plugin", + "description": "Rush plugin to archive project", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-archive-project-plugin/src/__mocks__/ora.js b/rush-plugins/rush-archive-project-plugin/src/__mocks__/ora.js new file mode 100644 index 0000000..2daa58a --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/__mocks__/ora.js @@ -0,0 +1,8 @@ +/* eslint-env es6 */ +const ora = require("ora"); + +module.exports = function (text) { + const spinner = ora(text); + spinner.stream = process.stdout; + return spinner; +}; diff --git a/rush-plugins/rush-archive-project-plugin/src/cli.ts b/rush-plugins/rush-archive-project-plugin/src/cli.ts new file mode 100644 index 0000000..fb0f009 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/cli.ts @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; +import { + Colors, + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; +import { promptRushUpdate } from "./logic/promptRushUpdate"; + +const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + await yargs(hideBin(process.argv)) + .command( + "archive", + "Archive a project", + (yargs) => { + return yargs + .option("packageName", { + type: "string", + describe: "The name of the package to archive", + }) + .option("gitCheckpoint", { + type: "boolean", + describe: "Create a git checkpoint before archival" + }) + .default('gitCheckpoint', true) + .demandOption(["packageName", "gitCheckpoint"]); + }, + async (argv) => { + const { archive } = await import("./commands/archive"); + try { + await archive(argv); + await promptRushUpdate({ + terminal, + }); + terminal.writeLine(Colors.green("Archive ALL DONE!")); + } catch (e: any) { + terminal.writeErrorLine(`Archive FAILED: ${e.message}`); + process.exit(1); + } + } + ) + .command( + "unarchive", + "Unarchive a project", + (yargs) => { + return yargs + .option("packageName", { + type: "string", + describe: "The name of the package to unarchive", + }) + .demandOption(["packageName"]); + }, + async (argv) => { + const { unarchive } = await import("./commands/unarchive"); + try { + await unarchive(argv); + await promptRushUpdate({ + terminal + }); + terminal.writeLine(Colors.green("Unarchive ALL DONE!")); + } catch (e: any) { + terminal.writeErrorLine(`Unarchive FAILED: ${e.message}`); + process.exit(1); + } + } + ) + .demandCommand(1, "You need at least one command before moving on") + .parse(); +} diff --git a/rush-plugins/rush-archive-project-plugin/src/commands/archive.ts b/rush-plugins/rush-archive-project-plugin/src/commands/archive.ts new file mode 100644 index 0000000..11472dd --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/commands/archive.ts @@ -0,0 +1,169 @@ +import type { + RushConfiguration, + RushConfigurationProject, +} from "@rushstack/rush-sdk"; +import { FileSystem, JsonFile, JsonObject } from "@rushstack/node-core-library"; +import * as path from "path"; +import * as tar from "tar"; +import { getCheckpointBranch, gitCheckIgnored, gitFullClean, pushGitBranch } from "../logic/git"; +import { getGraveyardInfo } from "../logic/graveyard"; +import { IProjectCheckpointMetadata, ProjectMetadata } from "../logic/projectMetadata"; +import ora from "ora"; +import inquirer from 'inquirer'; +import fs from 'fs'; +import { loadRushConfiguration } from "../logic/rushConfiguration"; +import { convertProjectMetadataToMD } from "../logic/generateMD"; + +interface IArchiveConfig { + packageName: string; + gitCheckpoint: boolean; + shouldPushGitCheckpoint?: boolean; +} + +export async function archive({ packageName, gitCheckpoint, shouldPushGitCheckpoint }: IArchiveConfig): Promise { + let spinner: ora.Ora | undefined; + const rushConfiguration: RushConfiguration = loadRushConfiguration(); + const monoRoot: string = rushConfiguration.rushJsonFolder; + const project: RushConfigurationProject | undefined = + rushConfiguration.getProjectByName(packageName); + if (!project) { + throw new Error(`Could not find project with package name ${packageName}`); + } + + // check project is depended by other projects + const consumingProjectNames: string[] = Array.from( + project.consumingProjects + ).map((x: RushConfigurationProject) => x.packageName); + if (consumingProjectNames.length) { + throw new Error(`Target project ${packageName} is depended by other ${ + consumingProjectNames.length + } project(s): +${consumingProjectNames.join(", ")}`); + } + + const { projectFolder, projectRelativeFolder } = project; + + // git clean -xdf + spinner = ora(`Cleaning ${projectRelativeFolder}`).start(); + gitFullClean(projectFolder); + spinner.succeed(`Clean ${projectRelativeFolder} complete`); + + const { graveyardRelativeFolder, tarballRelativeFolder, tarballFolder, tarballName } = + getGraveyardInfo({ + monoRoot, + packageName, + }); + FileSystem.ensureFolder(tarballFolder); + + if (gitCheckpoint) { + spinner = ora('Attempting to create a git checkpoint branch'); + const branchName: string = getCheckpointBranch(rushConfiguration.rushJsonFolder,packageName); + spinner.succeed(`Git Checkpoint created at branch: ${branchName}`); + let shouldPushBranch: boolean; + if (shouldPushGitCheckpoint === undefined) { + // Prompt user to push the newly created branch + const { pushBranch } = await inquirer.prompt([ + { type: 'confirm', name: 'pushBranch', message: 'Push checkpoint branch to remote?' } + ]) + shouldPushBranch = pushBranch; + } else { + shouldPushBranch = shouldPushGitCheckpoint; + } + + if (shouldPushBranch) { + pushGitBranch(rushConfiguration.rushJsonFolder, branchName); + } + // Add data to metadata file + const archivedProjectMetadataFilePath: string = path.join(monoRoot, graveyardRelativeFolder, 'projectCheckpoints.json'); + const archivedProjectMetadataMdFilePath: string = path.join(monoRoot, graveyardRelativeFolder, 'projectCheckpoints.md'); + let archivedProjectMetadataObject: { [key in string]: IProjectCheckpointMetadata } = {}; + if (FileSystem.exists(archivedProjectMetadataFilePath)) { + archivedProjectMetadataObject = JsonFile.load(archivedProjectMetadataFilePath); + } + // Try to pull a description from the package's package.json file + let description: string = ""; + const projectJson: string = `${project.projectFolder}/package.json`; + if (FileSystem.exists(projectJson)) { + const packageJson: any = JsonFile.load(`${project.projectFolder}/package.json`); + description = packageJson.description || ""; + } + archivedProjectMetadataObject[packageName] = { + checkpointBranch: branchName, + archivedOn: new Date().toISOString(), + description + } + JsonFile.save(archivedProjectMetadataObject, archivedProjectMetadataFilePath); + + fs.writeFileSync(archivedProjectMetadataMdFilePath, convertProjectMetadataToMD(archivedProjectMetadataObject)); + } + + // create a metadata.json file + spinner = ora(`Creating metadata.json for ${projectRelativeFolder}`).start(); + const rawRushJson: JsonObject = JsonFile.load(rushConfiguration.rushJsonFile); + const rawProjectConfig: JsonObject = rawRushJson.projects.find( + (x: JsonObject) => x.packageName === packageName + ); + const projectMetadata: ProjectMetadata = new ProjectMetadata( + rawProjectConfig + ); + + const projectMetadataFilepath: string = path.join( + projectFolder, + ProjectMetadata.FILENAME + ); + projectMetadata.save(projectMetadataFilepath); + spinner.succeed(`Created metadata.json for ${projectRelativeFolder}`); + + // create archive tarball + spinner = ora(`Creating tarball for ${projectRelativeFolder}`).start(); + try { + //tar -czf test.tar.gz -C project_relative_folder . + tar.create( + { + gzip: true, + file: tarballName, + sync: true, + cwd: projectFolder, + }, + ["."] + ); + } catch (e: any) { + throw new Error(`Failed to create tarball: ${e.message}`); + } + spinner.succeed(`Created tarball for ${projectRelativeFolder}`); + + // move the tarball to the graveyard folder + spinner = ora(`Moving tarball to ${tarballRelativeFolder}`).start(); + const finalTarballPath: string = path.join(tarballFolder, tarballName); + FileSystem.move({ + sourcePath: tarballName, + destinationPath: finalTarballPath, + }); + spinner.succeed(`Moved tarball to ${tarballRelativeFolder}`); + + // check if the tarball is ignored by git + spinner = ora(`Checking if tarball is ignored by git`).start(); + const checkIgnored: string = gitCheckIgnored( + rushConfiguration.rushJsonFolder, + finalTarballPath + ); + if (checkIgnored) { + throw new Error(`Tarball is ignored by git: ${checkIgnored}`); + } + spinner.succeed(`Tarball is not ignored by git`); + + // remove project config in rush.json + spinner = ora(`Removing project config from rush.json`).start(); + rawRushJson.projects = rawRushJson.projects.filter( + (x: JsonObject) => x.packageName !== packageName + ); + JsonFile.save(rawRushJson, rushConfiguration.rushJsonFile, { + updateExistingFile: true, + }); + spinner.succeed(`Removed project config from rush.json`); + + // delete project folder + spinner = ora(`Deleting project folder ${projectRelativeFolder}`).start(); + FileSystem.deleteFolder(projectFolder); + spinner.succeed(`Deleted project folder ${projectRelativeFolder}`); +} diff --git a/rush-plugins/rush-archive-project-plugin/src/commands/test/__snapshots__/archive.test.ts.snap b/rush-plugins/rush-archive-project-plugin/src/commands/test/__snapshots__/archive.test.ts.snap new file mode 100644 index 0000000..3c2e2f0 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/commands/test/__snapshots__/archive.test.ts.snap @@ -0,0 +1,6 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`archive archive package with dependent should not work with package has dependent 1`] = ` +"Target project @my-company/my-lib is depended by other 1 project(s): +@my-company/my-app" +`; diff --git a/rush-plugins/rush-archive-project-plugin/src/commands/test/archive.test.ts b/rush-plugins/rush-archive-project-plugin/src/commands/test/archive.test.ts new file mode 100644 index 0000000..99a2036 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/commands/test/archive.test.ts @@ -0,0 +1,127 @@ +import * as path from "path"; +import { Executable } from "@rushstack/node-core-library"; +import { archive } from "../archive"; +import { defaultGraveyardRelativeFolder } from "../../logic/graveyard"; + +const folderSet = new Set(); + +const resume = (folders: string[]) => { + for (const folder of folders) { + Executable.spawnSync("git", ["checkout", "."], { + currentWorkingDirectory: folder, + }); + Executable.spawnSync("git", ["clean", "-xdf"], { + currentWorkingDirectory: folder, + }); + } +}; + +describe("archive", () => { + afterAll(() => { + resume(Array.from(folderSet)); + }); + + describe("archive basic", () => { + const fixtureMonorepoPath = path.join( + __dirname, + "../../../", + "fixtures/monorepo-1" + ); + const fixtureMonorepoGraveyardPath = path.join( + fixtureMonorepoPath, + defaultGraveyardRelativeFolder + ); + folderSet.add(fixtureMonorepoPath); + folderSet.add(fixtureMonorepoGraveyardPath); + beforeEach(() => { + jest.spyOn(process, "cwd").mockReturnValue(fixtureMonorepoPath); + }); + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should not work with non existing package name", async () => { + const packageName = "non-exist"; + await expect( + archive({ + packageName, + gitCheckpoint: false + }) + ).rejects.toThrow( + `Could not find project with package name ${packageName}` + ); + }); + + describe("fixture monorepo", () => { + it("should work with fixture demo", async () => { + const packageName = "demo-project"; + await expect( + archive({ + packageName, + gitCheckpoint: false + }) + ).resolves.toBeUndefined(); + }); + }); + }); + + describe("archive package with scope", () => { + const fixtureMonorepoPath = path.join( + __dirname, + "../../../", + "fixtures/monorepo-3" + ); + const fixtureMonorepoGraveyardPath = path.join( + fixtureMonorepoPath, + defaultGraveyardRelativeFolder + ); + folderSet.add(fixtureMonorepoPath); + folderSet.add(fixtureMonorepoGraveyardPath); + beforeEach(() => { + jest.spyOn(process, "cwd").mockReturnValue(fixtureMonorepoPath); + }); + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should work with scoped package @my-company/my-app", async () => { + const packageName = "@my-company/my-app"; + await expect( + archive({ + packageName, + gitCheckpoint: false + }) + ).resolves.toBeUndefined(); + }); + }); + + describe("archive package with dependent", () => { + const fixtureMonorepoPath = path.join( + __dirname, + "../../../", + "fixtures/monorepo-5" + ); + const fixtureMonorepoGraveyardPath = path.join( + fixtureMonorepoPath, + defaultGraveyardRelativeFolder + ); + folderSet.add(fixtureMonorepoPath); + folderSet.add(fixtureMonorepoGraveyardPath); + beforeEach(() => { + jest.spyOn(process, "cwd").mockReturnValue(fixtureMonorepoPath); + }); + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should not work with package has dependent", async () => { + const packageName = "@my-company/my-lib"; + await expect( + archive({ + packageName, + gitCheckpoint: false + }) + ).rejects.toThrowErrorMatchingSnapshot(); + }); + }); +}); diff --git a/rush-plugins/rush-archive-project-plugin/src/commands/test/unarchive.test.ts b/rush-plugins/rush-archive-project-plugin/src/commands/test/unarchive.test.ts new file mode 100644 index 0000000..21680c4 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/commands/test/unarchive.test.ts @@ -0,0 +1,94 @@ +import * as path from "path"; +import { Executable } from "@rushstack/node-core-library"; +import { unarchive } from "../unarchive"; +import { defaultGraveyardRelativeFolder } from "../../logic/graveyard"; + +const folderSet = new Set(); + +const resume = (folders: string[]) => { + for (const folder of folders) { + Executable.spawnSync("git", ["checkout", "."], { + currentWorkingDirectory: folder, + }); + Executable.spawnSync("git", ["clean", "-xdf"], { + currentWorkingDirectory: folder, + }); + } +}; + +describe("unarchive", () => { + afterAll(() => { + resume(Array.from(folderSet)); + }); + + describe("unarchive basic", () => { + const fixtureMonorepoPath = path.join( + __dirname, + "../../../", + "fixtures/monorepo-2" + ); + const fixtureMonorepoGraveyardPath = path.join( + fixtureMonorepoPath, + defaultGraveyardRelativeFolder + ); + folderSet.add(fixtureMonorepoPath); + folderSet.add(fixtureMonorepoGraveyardPath); + + beforeEach(() => { + jest.spyOn(process, "cwd").mockReturnValue(fixtureMonorepoPath); + }); + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should not work with no existing package name", async () => { + const packageName = "non-exist"; + await expect( + unarchive({ + packageName, + }) + ).rejects.toThrow( + `Could not find tarball ${packageName}.tar.gz for package name ${packageName}` + ); + }); + + describe("fixture monorepo", () => { + it("should work with fixture demo", async () => { + const packageName = "demo-project"; + await expect( + unarchive({ + packageName, + }) + ).resolves.toBeUndefined(); + }); + }); + }); + + describe("unarchive package with scope", () => { + const fixtureMonorepoPath = path.join( + __dirname, + "../../../", + "fixtures/monorepo-4" + ); + const fixtureMonorepoGraveyardPath = path.join( + fixtureMonorepoPath, + defaultGraveyardRelativeFolder + ); + folderSet.add(fixtureMonorepoPath); + folderSet.add(fixtureMonorepoGraveyardPath); + beforeEach(() => { + jest.spyOn(process, "cwd").mockReturnValue(fixtureMonorepoPath); + }); + afterEach(() => { + jest.resetAllMocks(); + }); + it("should work with scoped package @my-company/my-app", async () => { + const packageName = "@my-company/my-app"; + await expect( + unarchive({ + packageName, + }) + ).resolves.toBeUndefined(); + }); + }); +}); diff --git a/rush-plugins/rush-archive-project-plugin/src/commands/unarchive.ts b/rush-plugins/rush-archive-project-plugin/src/commands/unarchive.ts new file mode 100644 index 0000000..93402c3 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/commands/unarchive.ts @@ -0,0 +1,101 @@ +import * as path from "path"; +import { FileSystem, JsonFile, JsonObject } from "@rushstack/node-core-library"; +import ora from "ora"; +import { getGraveyardInfo } from "../logic/graveyard"; +import * as tar from "tar"; +import fs from 'fs'; +import { IProjectCheckpointMetadata, ProjectMetadata } from "../logic/projectMetadata"; +import { loadRushConfiguration } from "../logic/rushConfiguration"; + +import type { RushConfiguration } from "@rushstack/rush-sdk"; +import { convertProjectMetadataToMD } from "../logic/generateMD"; + +export interface IUnarchiveConfig { + packageName: string; +} + +export async function unarchive({ + packageName, +}: IUnarchiveConfig): Promise { + let spinner: ora.Ora | undefined; + const rushConfiguration: RushConfiguration = loadRushConfiguration(); + + // check if package name is existing + if (rushConfiguration.getProjectByName(packageName)) { + throw new Error(`Package ${packageName} already exists`); + } + + const monoRoot: string = rushConfiguration.rushJsonFolder; + + // extract tarball + const { graveyardRelativeFolder, tarballName, tarballFolder } = getGraveyardInfo({ + monoRoot, + packageName, + }); + const tarballPath: string = path.join(tarballFolder, tarballName); + if (!FileSystem.exists(tarballPath)) { + throw new Error( + `Could not find tarball ${tarballName} for package name ${packageName}` + ); + } + spinner = ora(`Extracting ${tarballName}`).start(); + // tar xf .tar.gz + const extractWorkingFolder: string = path.join( + tarballFolder, + packageName.replace("/", "!") + ); + FileSystem.ensureFolder(extractWorkingFolder); + tar.extract({ + file: path.join(tarballFolder, tarballName), + sync: true, + cwd: extractWorkingFolder, + }); + spinner.succeed(); + + // Remove checkpoint metadata from file + const archivedProjectMetadataFilePath: string = path.join(monoRoot, graveyardRelativeFolder, 'projectCheckpoints.json'); + const archivedProjectMetadataMdFilePath: string = path.join(monoRoot, graveyardRelativeFolder, 'projectCheckpoints.md'); + if (FileSystem.exists(archivedProjectMetadataFilePath)) { + const metadataCheckpoints: { [key in string]: IProjectCheckpointMetadata } = JsonFile.load(archivedProjectMetadataFilePath); + delete metadataCheckpoints[packageName]; + JsonFile.save(metadataCheckpoints, archivedProjectMetadataFilePath); + fs.writeFileSync(archivedProjectMetadataMdFilePath, convertProjectMetadataToMD(metadataCheckpoints)); + } + + // read metadata + const projectMetadata: ProjectMetadata = ProjectMetadata.load( + path.join(extractWorkingFolder, ProjectMetadata.FILENAME) + ); + + const projectConfig: JsonObject = projectMetadata.projectConfig; + const projectRelativeFolder: string = projectConfig.projectFolder; + const projectFolder: string = path.join(monoRoot, projectRelativeFolder); + if (FileSystem.exists(projectFolder)) { + throw new Error(`Project folder ${projectRelativeFolder} already exists`); + } + + // move to project folder + spinner = ora(`Moving code to ${projectRelativeFolder}`).start(); + FileSystem.move({ + sourcePath: extractWorkingFolder, + destinationPath: projectFolder, + }); + spinner.succeed(); + + // resume project configuration to rush.json + spinner = ora(`Resuming project configuration to rush.json`).start(); + const rawRushJson: JsonObject = JsonFile.load(rushConfiguration.rushJsonFile); + rawRushJson.projects.push(projectConfig); + JsonFile.save(rawRushJson, rushConfiguration.rushJsonFile, { + updateExistingFile: true, + prettyFormatting: true, + }); + spinner.succeed(); + + spinner = ora(`Housekeeping`).start(); + // delete metadata + FileSystem.deleteFile(path.join(projectFolder, ProjectMetadata.FILENAME)); + // remove tarball from graveyard + FileSystem.deleteFile(tarballPath); + spinner.succeed(); +} diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/generateMD.ts b/rush-plugins/rush-archive-project-plugin/src/logic/generateMD.ts new file mode 100644 index 0000000..fb3a861 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/generateMD.ts @@ -0,0 +1,26 @@ +import json2md from 'json2md'; +import { IProjectCheckpointMetadata } from './projectMetadata'; + +// Generate a md file with the corresponding json content for archived projects +export const convertProjectMetadataToMD = (archivedProjectMetadataObject: { [key in string]: IProjectCheckpointMetadata }): string => { +// Try saving a md file of this json file + const mdFileContents: any = [ + { h2: "Archived Projects" } + ]; + const tableRows: any = [] + for (const [projectName, projectMetadata] of Object.entries(archivedProjectMetadataObject)) { + tableRows.push([ + projectName, + projectMetadata.checkpointBranch, + projectMetadata.description, + projectMetadata.archivedOn + ]) + } + mdFileContents.push({ + table: { + headers: ["Project Name", "Checkpoint Branch", "Description", "Archive Date"], + rows: tableRows + } + }) + return json2md(mdFileContents); +} \ No newline at end of file diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/git.ts b/rush-plugins/rush-archive-project-plugin/src/logic/git.ts new file mode 100644 index 0000000..082fdd5 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/git.ts @@ -0,0 +1,78 @@ +import { Executable } from "@rushstack/node-core-library"; + +import type { SpawnSyncReturns } from "child_process"; + +let checkedGitPath: boolean = false; +let gitPath: string | undefined; + +export const getGitPath = (): string | undefined => { + if (!checkedGitPath) { + checkedGitPath = true; + gitPath = Executable.tryResolve("git"); + } + return gitPath; +}; + +export const getGitPathOrThrow = (): string => { + const gitPath: string | undefined = getGitPath(); + if (!gitPath) { + throw new Error("Unable to find git."); + } + return gitPath; +}; + +export const gitFullClean = (cwd: string): void => { + const gitPath: string = getGitPathOrThrow(); + Executable.spawnSync(gitPath, ["clean", "-fdx"], { + currentWorkingDirectory: cwd, + }); +}; + +export const gitCheckIgnored = (cwd: string, filePath: string): string => { + const gitPath: string = getGitPathOrThrow(); + let result: string = ""; + try { + const process: SpawnSyncReturns = Executable.spawnSync( + gitPath, + ["check-ignore", "-v", filePath], + { + currentWorkingDirectory: cwd, + } + ); + if (process.status === 0) { + result = process.stdout.toString(); + } + } catch (e: any) { + if (e.message.includes("The command failed with exit code 1")) { + // ignore + } else { + // rethrow + throw e; + } + } + return result; +}; + +export const getCheckpointBranch = (cwd: string, branchName: string): string => { + const gitPath: string = getGitPathOrThrow(); + const currDate: string = new Date().toISOString().substring(0, 10); + const branchNameToCreate: string = `${branchName}-checkpoint-${currDate}`; + const process: SpawnSyncReturns = Executable.spawnSync(gitPath, ["branch", branchNameToCreate], { + currentWorkingDirectory: cwd, + }); + if (process.status === 128) { + throw new Error(`The passed branch name is invalid: ${branchNameToCreate}`) + } + + return branchNameToCreate; +} + +export const pushGitBranch = (cwd: string, branchName: string): void => { + const gitPath: string = getGitPathOrThrow(); + const process: SpawnSyncReturns = Executable.spawnSync(gitPath, ["push", "origin", `${branchName}:${branchName}`], { + currentWorkingDirectory: cwd, + }); + if (process.status !== 0) { + console.error('Could not push branch to origin'); + } +} \ No newline at end of file diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/graveyard.ts b/rush-plugins/rush-archive-project-plugin/src/logic/graveyard.ts new file mode 100644 index 0000000..2dfd233 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/graveyard.ts @@ -0,0 +1,55 @@ +import * as path from 'path'; +import { PackageName, IParsedPackageName, JsonFile, FileSystem } from '@rushstack/node-core-library'; +import { RushConfiguration } from '@rushstack/rush-sdk'; +import { loadRushConfiguration } from './rushConfiguration'; + +export const defaultGraveyardRelativeFolder: string = 'common/_graveyard'; + +export interface IGraveyardInfo { + graveyardRelativeFolder: string; + tarballFolder: string; + tarballRelativeFolder: string; + tarballName: string; +} + +export interface IGetGraveyardInfoParams { + monoRoot: string; + packageName: string; +} + +export interface IArchiveConfig { + graveyardFolder?: string; +} + +export const getGraveyardInfo = ({ monoRoot, packageName }: IGetGraveyardInfoParams): IGraveyardInfo => { + const rushConfiguration: RushConfiguration = loadRushConfiguration(); + // Check for config file + const pluginOptionsJsonFilePath: string = path.join( + rushConfiguration.rushPluginOptionsFolder, + `rush-archive-project-plugin.json` + ); + + let graveyardRelativeFolder: string = defaultGraveyardRelativeFolder; + let archiveConfigs: IArchiveConfig | undefined; + try { + archiveConfigs = JsonFile.load(pluginOptionsJsonFilePath); + } catch (e) { + if (!FileSystem.isNotExistError(e as Error)) { + throw e; + } + } + + if (archiveConfigs?.graveyardFolder) { + graveyardRelativeFolder = archiveConfigs.graveyardFolder; + } + + const parsedPackageName: IParsedPackageName = PackageName.parse(packageName); + const tarballRelativeFolder: string = path.join(graveyardRelativeFolder, parsedPackageName.scope); + const tarballFolder: string = path.join(monoRoot, tarballRelativeFolder); + return { + graveyardRelativeFolder, + tarballFolder, + tarballRelativeFolder, + tarballName: `${parsedPackageName.unscopedName}.tar.gz` + }; +}; diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/projectMetadata.ts b/rush-plugins/rush-archive-project-plugin/src/logic/projectMetadata.ts new file mode 100644 index 0000000..4d6f927 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/projectMetadata.ts @@ -0,0 +1,36 @@ +import { JsonObject, JsonFile } from "@rushstack/node-core-library"; +export class ProjectMetadata { + private _projectConfig: JsonObject; + public static FILENAME: string = "rush-project-metadata.json"; + + public constructor(projectConfig: JsonObject) { + this._projectConfig = projectConfig; + } + + public static load(filePath: string): ProjectMetadata { + const { projectConfig } = JsonFile.load(filePath); + return new ProjectMetadata(projectConfig); + } + + public save(filePath: string): void { + JsonFile.save( + { + projectConfig: this._projectConfig, + }, + filePath, + { + ensureFolderExists: true, + } + ); + } + + public get projectConfig(): JsonObject { + return this._projectConfig; + } +} + +export interface IProjectCheckpointMetadata { + checkpointBranch: string; + archivedOn: string; + description: string; +} \ No newline at end of file diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/promptRushUpdate.ts b/rush-plugins/rush-archive-project-plugin/src/logic/promptRushUpdate.ts new file mode 100644 index 0000000..8aa36e1 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/promptRushUpdate.ts @@ -0,0 +1,46 @@ +import type { RushConfiguration } from "@rushstack/rush-sdk"; +import type { ITerminal } from "@rushstack/node-core-library"; +import { Executable } from "@rushstack/node-core-library"; +import * as path from "path"; +import { loadRushConfiguration } from "./rushConfiguration"; + +export interface IPromptRushUpdateParams { + terminal: ITerminal; +} + +export async function promptRushUpdate({ + terminal, +}: IPromptRushUpdateParams): Promise { + const { prompt } = await import("inquirer"); + interface IShouldRunRushUpdateAnswer { + shouldRunRushUpdate: boolean; + } + const rushConfiguration: RushConfiguration = loadRushConfiguration(); + const runRushJSPath: string = path.join( + rushConfiguration.commonScriptsFolder, + "install-run-rush.js" + ); + + const { shouldRunRushUpdate } = await prompt([ + { + type: "confirm", + name: "shouldRunRushUpdate", + message: "Run rush update right now?", + default: true, + }, + ]); + + if (shouldRunRushUpdate) { + terminal.writeLine("Run rush update..."); + try { + Executable.spawnSync("node", [runRushJSPath, "update"], { + stdio: "inherit", + }); + } catch (e) { + terminal.writeErrorLine("Rush update failed, please run it manually."); + } + terminal.writeLine("Rush update successfully."); + } else { + terminal.writeWarningLine("Rush update skipped, please run it manually."); + } +} diff --git a/rush-plugins/rush-archive-project-plugin/src/logic/rushConfiguration.ts b/rush-plugins/rush-archive-project-plugin/src/logic/rushConfiguration.ts new file mode 100644 index 0000000..f8e86e1 --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/src/logic/rushConfiguration.ts @@ -0,0 +1,24 @@ +import { RushConfiguration } from "@rushstack/rush-sdk"; + +const cwd2rushConfiguration: Record = {}; + +export const loadRushConfiguration = ( + cwd: string = process.cwd() +): RushConfiguration => { + let rushConfiguration: RushConfiguration | undefined = + cwd2rushConfiguration[cwd]; + if (!rushConfiguration) { + try { + rushConfiguration = RushConfiguration.loadFromDefaultLocation({ + startingFolder: cwd, + }); + } catch { + // no-catch + } + if (!rushConfiguration) { + throw new Error("Could not load rush configuration"); + } + cwd2rushConfiguration[cwd] = rushConfiguration; + } + return rushConfiguration; +}; diff --git a/rush-plugins/rush-archive-project-plugin/tsconfig.json b/rush-plugins/rush-archive-project-plugin/tsconfig.json new file mode 100644 index 0000000..664294a --- /dev/null +++ b/rush-plugins/rush-archive-project-plugin/tsconfig.json @@ -0,0 +1,95 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/.eslintrc.js b/rush-plugins/rush-audit-cache-plugin/.eslintrc.js new file mode 100644 index 0000000..925d67c --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-audit-cache-plugin/.gitignore b/rush-plugins/rush-audit-cache-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/.npmignore b/rush-plugins/rush-audit-cache-plugin/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-audit-cache-plugin/CHANGELOG.json b/rush-plugins/rush-audit-cache-plugin/CHANGELOG.json new file mode 100644 index 0000000..bb82429 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/CHANGELOG.json @@ -0,0 +1,221 @@ +{ + "name": "rush-audit-cache-plugin", + "entries": [ + { + "version": "0.2.3", + "tag": "rush-audit-cache-plugin_v0.2.3", + "date": "Wed, 23 Aug 2023 05:01:48 GMT", + "comments": { + "patch": [ + { + "comment": "rush-audit-cache-plugin support dependsOnAdditionalFiles" + } + ] + } + }, + { + "version": "0.2.2", + "tag": "rush-audit-cache-plugin_v0.2.2", + "date": "Mon, 05 Jun 2023 04:43:06 GMT", + "comments": { + "patch": [ + { + "comment": "build cache audit tool support phased command" + } + ] + } + }, + { + "version": "0.2.1", + "tag": "rush-audit-cache-plugin_v0.2.1", + "date": "Wed, 01 Mar 2023 04:51:48 GMT", + "comments": { + "patch": [ + { + "comment": "audit cache if select project, will not audit dependencies projects" + } + ] + } + }, + { + "version": "0.2.0", + "tag": "rush-audit-cache-plugin_v0.2.0", + "date": "Tue, 28 Feb 2023 08:06:50 GMT", + "comments": { + "minor": [ + { + "comment": "rush audit cache plugin support multiple projects" + } + ] + } + }, + { + "version": "0.1.10", + "tag": "rush-audit-cache-plugin_v0.1.10", + "date": "Mon, 12 Dec 2022 02:58:12 GMT", + "comments": { + "patch": [ + { + "comment": "fix outputFolderNames bug and support schema" + } + ] + } + }, + { + "version": "0.1.9", + "tag": "rush-audit-cache-plugin_v0.1.9", + "date": "Mon, 28 Nov 2022 08:16:15 GMT", + "comments": { + "patch": [ + { + "comment": "add repo audit cache config" + } + ] + } + }, + { + "version": "0.1.8", + "tag": "rush-audit-cache-plugin_v0.1.8", + "date": "Fri, 25 Nov 2022 06:42:23 GMT", + "comments": { + "patch": [ + { + "comment": "fix rush-audit-cache-plugin parser file director error" + } + ] + } + }, + { + "version": "0.1.7", + "tag": "rush-audit-cache-plugin_v0.1.7", + "date": "Tue, 22 Nov 2022 05:56:31 GMT", + "comments": { + "patch": [ + { + "comment": "change output of audit specific project and support rush-audit-cache.json" + } + ] + } + }, + { + "version": "0.1.6", + "tag": "rush-audit-cache-plugin_v0.1.6", + "date": "Mon, 07 Nov 2022 13:26:33 GMT", + "comments": { + "patch": [ + { + "comment": "rush audit cache add some low risk path" + } + ] + } + }, + { + "version": "0.1.5", + "tag": "rush-audit-cache-plugin_v0.1.5", + "date": "Mon, 07 Nov 2022 12:07:21 GMT", + "comments": { + "patch": [ + { + "comment": "fix linux parse log bug" + } + ] + } + }, + { + "version": "0.1.4", + "tag": "rush-audit-cache-plugin_v0.1.4", + "date": "Mon, 07 Nov 2022 08:20:01 GMT", + "comments": { + "patch": [ + { + "comment": "use -ff to separate strace log and disable rush build cache when rebuild" + } + ] + } + }, + { + "version": "0.1.3", + "tag": "rush-audit-cache-plugin_v0.1.3", + "date": "Thu, 03 Nov 2022 02:10:44 GMT", + "comments": { + "patch": [ + { + "comment": "rush audit cache add --exclude parameter and filter directory" + } + ] + } + }, + { + "version": "0.1.2", + "tag": "rush-audit-cache-plugin_v0.1.2", + "date": "Thu, 27 Oct 2022 13:12:33 GMT", + "comments": { + "patch": [ + { + "comment": "rush install before run rebuild" + } + ] + } + }, + { + "version": "0.1.1", + "tag": "rush-audit-cache-plugin_v0.1.1", + "date": "Wed, 26 Oct 2022 13:03:49 GMT", + "comments": { + "patch": [ + { + "comment": "fix rush-audit-cache-plugin rebuild bug" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-audit-cache-plugin_v0.1.0", + "date": "Wed, 26 Oct 2022 07:19:37 GMT", + "comments": { + "minor": [ + { + "comment": "Add --all parameter to select all cache configured projects" + } + ] + } + }, + { + "version": "0.0.3", + "tag": "rush-audit-cache-plugin_v0.0.3", + "date": "Fri, 21 Oct 2022 01:41:04 GMT", + "comments": { + "patch": [ + { + "comment": "Fix rush project json path" + } + ] + } + }, + { + "version": "0.0.2", + "tag": "rush-audit-cache-plugin_v0.0.2", + "date": "Wed, 19 Oct 2022 14:08:21 GMT", + "comments": { + "patch": [ + { + "comment": "Fix shellCommand" + } + ] + } + }, + { + "version": "0.0.1", + "tag": "rush-audit-cache-plugin_v0.0.1", + "date": "Wed, 19 Oct 2022 14:02:29 GMT", + "comments": { + "patch": [ + { + "comment": "Initial Release" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-audit-cache-plugin/CHANGELOG.md b/rush-plugins/rush-audit-cache-plugin/CHANGELOG.md new file mode 100644 index 0000000..05b623c --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/CHANGELOG.md @@ -0,0 +1,130 @@ +# Change Log - rush-audit-cache-plugin + +This log was last generated on Wed, 23 Aug 2023 05:01:48 GMT and should not be manually modified. + +## 0.2.3 +Wed, 23 Aug 2023 05:01:48 GMT + +### Patches + +- rush-audit-cache-plugin support dependsOnAdditionalFiles + +## 0.2.2 +Mon, 05 Jun 2023 04:43:06 GMT + +### Patches + +- build cache audit tool support phased command + +## 0.2.1 +Wed, 01 Mar 2023 04:51:48 GMT + +### Patches + +- audit cache if select project, will not audit dependencies projects + +## 0.2.0 +Tue, 28 Feb 2023 08:06:50 GMT + +### Minor changes + +- rush audit cache plugin support multiple projects + +## 0.1.10 +Mon, 12 Dec 2022 02:58:12 GMT + +### Patches + +- fix outputFolderNames bug and support schema + +## 0.1.9 +Mon, 28 Nov 2022 08:16:15 GMT + +### Patches + +- add repo audit cache config + +## 0.1.8 +Fri, 25 Nov 2022 06:42:23 GMT + +### Patches + +- fix rush-audit-cache-plugin parser file director error + +## 0.1.7 +Tue, 22 Nov 2022 05:56:31 GMT + +### Patches + +- change output of audit specific project and support rush-audit-cache.json + +## 0.1.6 +Mon, 07 Nov 2022 13:26:33 GMT + +### Patches + +- rush audit cache add some low risk path + +## 0.1.5 +Mon, 07 Nov 2022 12:07:21 GMT + +### Patches + +- fix linux parse log bug + +## 0.1.4 +Mon, 07 Nov 2022 08:20:01 GMT + +### Patches + +- use -ff to separate strace log and disable rush build cache when rebuild + +## 0.1.3 +Thu, 03 Nov 2022 02:10:44 GMT + +### Patches + +- rush audit cache add --exclude parameter and filter directory + +## 0.1.2 +Thu, 27 Oct 2022 13:12:33 GMT + +### Patches + +- rush install before run rebuild + +## 0.1.1 +Wed, 26 Oct 2022 13:03:49 GMT + +### Patches + +- fix rush-audit-cache-plugin rebuild bug + +## 0.1.0 +Wed, 26 Oct 2022 07:19:37 GMT + +### Minor changes + +- Add --all parameter to select all cache configured projects + +## 0.0.3 +Fri, 21 Oct 2022 01:41:04 GMT + +### Patches + +- Fix rush project json path + +## 0.0.2 +Wed, 19 Oct 2022 14:08:21 GMT + +### Patches + +- Fix shellCommand + +## 0.0.1 +Wed, 19 Oct 2022 14:02:29 GMT + +### Patches + +- Initial Release + diff --git a/rush-plugins/rush-audit-cache-plugin/LICENSE b/rush-plugins/rush-audit-cache-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-audit-cache-plugin/README.md b/rush-plugins/rush-audit-cache-plugin/README.md new file mode 100644 index 0000000..3b750c7 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/README.md @@ -0,0 +1,24 @@ +# rush-audit-cache-plugin + +A diagnostic tool for rush build cache + +# Prerequisite + +- Rush.js >= 5.57.0 +- strace >= 4.26 in Linux + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Running `audit-cache` command + +``` +rush audit-cache --project +``` + +# Tech Note + +[rush audit-cache tech note](./docs/rush-audit-cache-tech-note.md) \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/command-line.json b/rush-plugins/rush-audit-cache-plugin/command-line.json new file mode 100644 index 0000000..2f24dfb --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/command-line.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "audit-cache", + "commandKind": "global", + "summary": "Audit cache configuration by diagnosing the build processes of the target project and its dependencies", + "shellCommand": "node /lib/bin.js", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "stringList", + "description": "The package name of the project", + "longName": "--project", + "shortName": "-p", + "argumentName": "PACKAGE_NAME", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Audit all cache configured project", + "longName": "--all", + "shortName": "-a", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "stringList", + "description": "Exclude package from audit cache", + "longName": "--exclude", + "shortName": "-e", + "argumentName": "EXCLUDE_PACKAGE_NAME", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "stringList", + "description": "Phased commands need to be audit", + "longName": "--phased-commands", + "shortName": "-P", + "argumentName": "PHASED_COMMANDS_NAMES", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "string", + "description": "verbosity that can be increased", + "longName": "--verbose", + "shortName": "-v", + "argumentName": "VERBOSE", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "flag", + "description": "show current version", + "longName": "--version", + "shortName": "-V", + "associatedCommands": ["audit-cache"], + "required": false + }, + { + "parameterKind": "string", + "description": "Specifies the maximum number of concurrent processes to launch during a build. (eg. '50% | '5')", + "longName": "--parallelism", + "shortName": "-c", + "argumentName": "COUNT", + "associatedCommands": ["audit-cache"], + "required": false + } + ] +} diff --git a/rush-plugins/rush-audit-cache-plugin/config/heft.json b/rush-plugins/rush-audit-cache-plugin/config/heft.json new file mode 100644 index 0000000..978c70b --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/config/heft.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + }, + { + "actionKind": "copyFiles", + "heftEvent": "pre-compile", + "actionId": "copySchemas", + "copyOperations": [ + { + "sourceFolder": "src", + "destinationFolders": ["lib"], + "includeGlobs": ["schemas/*.json"] + } + ] + } + ], + "heftPlugins": [{ "plugin": "@rushstack/heft-jest-plugin" }] +} diff --git a/rush-plugins/rush-audit-cache-plugin/config/jest.config.json b/rush-plugins/rush-audit-cache-plugin/config/jest.config.json new file mode 100644 index 0000000..b6f305e --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/config/jest.config.json @@ -0,0 +1,3 @@ +{ + "extends": "@rushstack/heft-jest-plugin/includes/jest-shared.config.json" +} diff --git a/rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-arch.png b/rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..8f10420af418833c6f656b510c919ba3604768dd GIT binary patch literal 135548 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

M&Wr9P=lI}WqI}K}8z)(_=tiTN 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 literal 0 HcmV?d00001 diff --git a/rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-demo-usage.png b/rush-plugins/rush-audit-cache-plugin/docs/media/rush-audit-cache-demo-usage.png new file mode 100644 index 0000000000000000000000000000000000000000..78b404a44d137103ec0dd090bb76e49b62bd8206 GIT binary patch literal 470465 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

MePO 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 BR1Gq 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%0Dd$UFAw$wn@N@j96T3;{ON=RVT%h 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

HZ`WICs{846A>wH8Vi54-;Ms3p@KK|d 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

hpxtnFL(;h< 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ⅆuToh}u*o-uIr$Uo5$M$hpYmDJoR6Vr_2 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�o{IksvdSMI#LHy$ zU;C7k==rk>htL7T{Y4})@a^M(Ykck39_nlz2B0M?ObMR9?{52P%- zKA{AE<&{mStxQy#f#HC!I&QzkE;vN-L$~z!lv$l~CJZBMMiRLaK6+&hmrMQM7 zh_p!1!nU(fPIF-8B5y>qazatWQntUTBPa$;c=dYBeWzAWpWZ{MhS*erF{P)qU=ypr z%w^TiwGpDj?)HHG{de=@TTW~cq8>~yJg_+U+Bu6?YK$izGG>7On$H(&o&97o;u z2pS)MMI+xgQ}V8b%?Qs$@$>U658PTn5ph`9&K8_W1e~@I zK~IksQ$-GoaLT{)@%Mm^=YnTIcihtw)6@eXd(tAACTqgt8~a`{8=;Yrkt;Rn&F|M@ z2iaDqK_q_5h`+nxg}J)0P)TH}aGx<=jhOgg5b~$_4z&^yw6)}ldOWi_+jUQG##qp} zXtfJSK<^Pvlc@rTUcI^;>H5M6q<6ChGwBxVO<1m9?d|QT-oC!OJqj%(MXU~m#3}?X zVkV}`y+oKO#_IHPk5nUYCi4Leq-WRZx-aM<3ITMh*@I@RT-4(KBEZx|AI3bpB1b-!XH*Ev=n(eqU1#m_$d4{+=*e1f&ywZUaJ%=^83T z;{Dk0%ETW-tJ~k9=5Wr>7v5%q?vzc`yv?<1%_Q-`rio@34GSa`SY~ia88JoP8rPA= z^Uy5%ksW8_9q(@Zg09ExLF!Z%MD4Iw_fCep6-0ghdmaM*^XzE={=Dy=R^Ur^iOX=t ztIE_@!^S|N?J(fbG!c@DTy!PV4j3bS=~K9Qp|FsU&Rog<@OSb|D7-4+uHIg&PORWv zG7#k6EqfAMUX}#XjT0=2G=J!mj7O-QP=(-Lrc))oySa^IJ(J{O;*{O!dePn5yIh#4 z>VPkmi{O`9*iraRgqVu^b4OD5;p?*}O(9bUu)F)K9gS{uU|`@OVuys%Ul(y*Pa*&z zJl_k6eDHasz0R25E>>}KG^hFc>5qljXjkQx!jr-f1Ly;o-j}++YEzGi5YJKb(q$aJ zRxWJX+S+g4pnLHWrV}V7I9QC>-4{AjY}t!RelPR#Yjc?YE;y?ufokK=gQP*JerPK0 zot2~xMq8fLgTFV*SExvMj_z)@0zavxLp6CrqygM*{s!TOq! zf%A>l;#b4IB77~M+Xi6)VUiRbVc`IQMx|_N5StmAp0z%ugj1(PfsJstie@<`m_BI^4Ao!D_2(wPISed%%T>i&oMhb9O~Ir?;(v>_gde6v)PqS8222q- zF%g1@Nx|Xoz`)JH1SKzL^eIsh3&}+g!KjkN$f?UwSF-vye2K7wx_vLhKTueI681HB zbNGJrwS@fmY#;^`30Ms67oi)%1rg)sj@{e;!jsW^7x|?b)zg%nx%21VqW-$}%2l8q z&iwQe0~1-=-FS6CMq?L0E{sbibBdm^p)B+3F|wdtvEj^~w8}28n6quvN$jRNBozAv z11^#RZevVq*gNn7qP!6z|2=P8^bsIV8HZ{C7a84wb$?hm|CXj!rxo)SK=%?LRA67{ z)UJ;W^Bnv(A*B(30v43p_wf4ez)g`OELTYz&@B_l!+R(Ox461s*SZd{^=Z6W0!vf` zCRJZEhs=r+?2DUc9^QI4uV~b04(rru-EIWduU&eYPq=ovPt6>1hJ_(P1W`l&=~dw; zmj>%-Z8NGDCPvW<;|2?Q+SIhZxrt`;xh$BrPNs|)Fzqoiu3utwcu=Q9W&Hv+BGqUX zI}eEFVI&*W_Vp|*GC&One|q|q+=)dOg{Xe*D~c3>FQuDo_{KQ_v22+)e;Wig_#ZKl|3jhJ4k|_B%eQZq84_8wE`^h zGbj-}42(4Cs_g$T@|uYMJEs1Rp!ffN`jPm*c9s7z_Wr*=eGk9tww}3sqzMFR% ifQX*}xc?eN;I_Z8>apY*F&LozYmk*xk^qXCg#2G=-xNjw literal 0 HcmV?d00001 diff --git a/rush-plugins/rush-audit-cache-plugin/docs/proposal-for-rush-build-diagnostic-tool.md b/rush-plugins/rush-audit-cache-plugin/docs/proposal-for-rush-build-diagnostic-tool.md new file mode 100644 index 0000000..d82be41 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/docs/proposal-for-rush-build-diagnostic-tool.md @@ -0,0 +1,44 @@ +# Background + +Our WebArch Engineering team wants to guide users in TikTok Monorepo to enable rush build cache feature for their projects. The main work is to configure a `rush-project.json` for each project. The challenge here is to correctly configure this file, because +- There are a variety of building toolchain that are used in TikTok Monorepo. Library maintainers may not be familiar with the details of each building tool. +- A wong cache artifact may cause frustration for developers. It may take hours to realize that an error is caused by a malfunctioning cache, which lowers the confidence of using build cache and may even lead to a decision to totally disable build cache feature. + +# Term: Hermeticity + +A build is hermetic if it is not affected by details of the environment where it is performed. + +Bazel has a official doc about it https://bazel.build/basics/hermeticity. + +# Why is keeping project hermetic important? + +- **Speed**: Hermeticity is a prerequisite for generally desirable features like remote caching and remote execution. This means that the inhermeticity of a project leads to malfunctioning remote cache. One should be aware of reusing remote build cache for a in-hermetic project. +- **Multiple build**: You can build multiple hermetic builds on the same machine, each build using different tools and versions. Imaging running multiple builds with a tool which writes logs to one constant file path, such as "/tmp/compiler.log". +- **Reproducibility**: Hermetic builds are good for troubleshooting because you know the exact conditions that produced the build. + +# How to identify non-hermeticity? + +In general, detecting non-hermeticity is hard. The major sources includes: +- **File system**: If tools are invoked in a way that does not limit their access to the contents of the file system, the output of these tools can be influenced by extraneous files that might be present during the build. Imagine the toolchain **reads** a base config file under another project folder which is not declared as one of the "devDependencies" of the building project. Alternatively, suppose the compiler **writes** an output to a folder path that is not saved/restored by the cache. +- **Environment**: It is very hard to ensure identical environments on different machines, especially developer machines. Restoring a cached output may produce incorrect results if the output is influenced by a shell environment variable that is not represented by the cache key. +- **Others**: There are many other sources of non-termeticity. For example, + - Arbitrary execustion outside of building process: For example, `pnpm install` may build native components with whichever compiler is in "PATH", linking against whichever system libraries are found. + - Performing any non-deterministic actions: Creating archives(zip, tar, etc) is a good example: The order of directory listings as well as timestamps are usually non- deterministic. The [reprodubile-builds](https://reproducible-builds.org/docs/archives/) project is a great resource to learn about these issues and how to circumvent them. + +# Detecting hermeticity issues + +Now, we can understand the difficulty of detecting hermeticity issues. But we still need to try our best to help users to do it. That's where a rush build diagnostic tool comes into rescue. + +## Trace file system calls + +With the help of external trace tools, we can trace system calls, especially the interactions between the build process and file system. A log is the ground truth about what files are accessed during the build. Developers can understand the building process better by checking all the file inputs and outputs. Moreover, the diagnostic tool can generate a friendly report by comparing the analyzed result with the project configuration. + +Ref: [Rush audit-cache tech note](./rush-audit-cache-tech-note.md) + +## Limit environment variables + +A general way to eliminate the influence of environment variables on different machines is to control the inheritance of the environment variables. This may need a new feature proposal in Rush.js to explicitly inherit the values of a given list of environment variables. Extra care must be taken in this case to guarantee that value stays reasonably stable. e.g. it is not an absolute path which can vary from machine to machine. + +# Reference + +- [How to keep a Bazel project hermetic](https://www.tweag.io/blog/2022-09-15-hermetic-bazel/) \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/docs/rush-audit-cache-tech-note.md b/rush-plugins/rush-audit-cache-plugin/docs/rush-audit-cache-tech-note.md new file mode 100644 index 0000000..147aeba --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/docs/rush-audit-cache-tech-note.md @@ -0,0 +1,36 @@ +# Rush audit-cache tech note + +The **"rush audit-cache"** feature is a diagnostic tool for Rush.js that allows an engineer to monitor the building process of one project. + +Goals: + +- When setting up a new project, provide an easy way to validate that the build cache configuration correctly reflects the toolchain's filesystem inputs and outputs +- If an engineer encounters a failure that is suspected to be a cache malfunction, provide an easy way to investigate + +Non-goals: + +- Continuous monitoring/validation of every build: In our initial implementation, the analysis may significantly impact build times. The feature will only be available if the OS supports the strace native tool and it has been installed. + +During build projects, Rush audit-cache leverages external tools to trace system calls and signals, such as [strace](https://man7.org/linux/man-pages/man1/strace.1.html). This includes file system access for the complete life of building. And then detecting potential issues by analyzing the tracing log. + +In our initial proof of concept implementation, use of **rush audit-cache** will require the Linux operating system, because of the dependency on the **strace** tool. This can be changed later by supporting tracing tools for other platforms, such as [dtrace](https://www.brendangregg.com/dtrace.html) in MacOS. + +# Design Overview + +Rush audit-cache logically consists of the following parts: +- A mechanism for tracing system calls of file access for a process, including forked processes. +- A mechanism for analyzing the trace log to get all inputs and outputs via file system +- A mechanism for reporting issues by comparing project build cache configuration with trace log. + +# Design Details + +![rush-audit-cache-arch](./media/rush-audit-cache-arch.png) + +1. Get `TraceExecutor` according to the OS platform. e.g. `LinuxTraceExecutor` for Linux platform. +2. `TraceExecutor` spawns a child process with `strace` command. `strace` will trace all system calls of the child process and its forked processes. +3. `TraceExecutor` reads the trace log from `strace` and parses it to get all file system access events. +4. `Analyzer` analyzes the trace log with rush project configurations and detects potential issues. + +# Reference + +- [Proposal for rush build diagnostic tool](./proposal-for-rush-build-diagnostic-tool.md) \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/lint-staged.config.cjs b/rush-plugins/rush-audit-cache-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-audit-cache-plugin/package.json b/rush-plugins/rush-audit-cache-plugin/package.json new file mode 100644 index 0000000..c80b7ac --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/package.json @@ -0,0 +1,43 @@ +{ + "name": "rush-audit-cache-plugin", + "version": "0.2.3", + "description": "A diagnostic tool for rush build cache", + "keywords": [ + "rush", + "plugin", + "command", + "build", + "cache" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-audit-cache-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "commander": "~9.4.0", + "ignore": "5.1.9" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-jest-plugin": "~0.1.53", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json b/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..1549c3a --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/rush-plugin-manifest.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-audit-cache-plugin", + "description": "A diagnostic tool for rush build cache", + "commandLineJsonFilePath": "command-line.json", + "optionsSchema": "lib/schemas/plugin-options.schema.json" + } + ] +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/auditCache.ts b/rush-plugins/rush-audit-cache-plugin/src/auditCache.ts new file mode 100644 index 0000000..8ff1999 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/auditCache.ts @@ -0,0 +1,191 @@ +import path from 'path'; + +import { RushConfiguration, RushConfigurationProject } from '@rushstack/rush-sdk'; +import { Colors, FileSystem, ITerminal } from '@rushstack/node-core-library'; + +import { AUDIT_CACHE_FOLDER } from './helpers/constants'; +import { TraceExecutorFactory } from './core/TraceExecutor'; +import { BaseTraceExecutor, IBaseTraceExecutorOptions, ITraceResult } from './core/base/BaseTraceExecutor'; +import { AuditCacheAnalyzer, IAnalyzeResult } from './core/Analyzer'; +import { getAllCacheConfiguredProjects } from './helpers/rushProject'; + +export interface IAuditCacheOptions { + projectNames: string[]; + terminal: ITerminal; + checkAllCacheConfiguredProject: boolean; + exclude: string[]; + parallelism?: string; + phasedCommands: string[]; +} + +export interface IAuditCacheResult { + traceResult: ITraceResult; + analyzeResult: IAnalyzeResult; +} + +export async function auditCache(options: IAuditCacheOptions): Promise { + const { projectNames, terminal, checkAllCacheConfiguredProject, exclude, parallelism, phasedCommands } = + options; + + terminal.writeDebugLine(`exclude: ${exclude}`); + + const rushConfiguration: RushConfiguration = RushConfiguration.loadFromDefaultLocation(); + terminal.writeVerboseLine('Rush configuration loaded'); + + const auditCacheProjects: RushConfigurationProject[] = []; + + if (!checkAllCacheConfiguredProject) { + const notExistProjects: string[] = []; + projectNames.forEach((projectName) => { + const rushConfigurationProject: RushConfigurationProject | undefined = + rushConfiguration.findProjectByShorthandName(projectName); + if (!rushConfigurationProject) { + notExistProjects.push(projectName); + return; + } + auditCacheProjects.push(rushConfigurationProject); + terminal.writeDebugLine( + `Audit cache projects ${auditCacheProjects.map(({ packageName }) => packageName).join(',')}` + ); + }); + + if (notExistProjects.length) { + throw new Error(`Projects ${notExistProjects.join(',')} not found`); + } + } else { + const allCacheConfiguredProjects: RushConfigurationProject[] = + getAllCacheConfiguredProjects(rushConfiguration); + if (!allCacheConfiguredProjects.length) { + throw new Error('there is no cache configured project to audit'); + } + const allNeedCacheAuditProjects: RushConfigurationProject[] = allCacheConfiguredProjects.filter( + ({ packageName }) => !exclude.find((name) => name === packageName) + ); + + auditCacheProjects.push(...allNeedCacheAuditProjects); + const allBuildCacheConfiguredProjects: string[] = allNeedCacheAuditProjects.map((p) => p.packageName); + terminal.writeDebugLine( + `Find build cache configured projects ${allBuildCacheConfiguredProjects.join(',')}` + ); + } + + const tempPath: string = rushConfiguration.commonTempFolder; + const auditCacheFolder: string = path.join(tempPath, AUDIT_CACHE_FOLDER); + + FileSystem.ensureEmptyFolder(auditCacheFolder); + + const traceExecutorOptions: IBaseTraceExecutorOptions = { + projects: auditCacheProjects, + logFolder: auditCacheFolder, + terminal, + parallelism + }; + const traceExecutor: BaseTraceExecutor = TraceExecutorFactory.create(traceExecutorOptions); + + const traceResult: ITraceResult = await traceExecutor.execAsync(); + + const analyzer: AuditCacheAnalyzer = new AuditCacheAnalyzer({ + rushConfiguration, + phasedCommands + }); + + terminal.writeLine(''); + terminal.writeLine('Analyzing trace result...'); + + const analyzeResult: IAnalyzeResult = analyzer.analyze(traceResult); + + const resultJsonFile: string = path.join(auditCacheFolder, 'result.json'); + FileSystem.writeFile( + resultJsonFile, + JSON.stringify( + analyzeResult, + (key, value) => { + if (value instanceof Set) { + return Array.from(value); + } + return value; + }, + 2 + ) + ); + + terminal.writeVerboseLine(`Audit cache result saved to ${resultJsonFile}`); + + if (!checkAllCacheConfiguredProject) { + terminal.writeLine( + `Audit cache for project ${auditCacheProjects[0].packageName}${ + auditCacheProjects.length > 1 + ? ` and its dependencies ${auditCacheProjects + .slice(1) + .map(({ packageName }) => packageName) + .join(',')}` + : '' + }` + ); + } + + const writeProjectAnalyzeResult = (params: { + result: IAnalyzeResult[string]; + packageName: string; + }): void => { + const { result, packageName } = params; + terminal.writeLine(`======== project ${packageName} ========`); + + const { highRisk, lowRisk } = result; + terminal.write('It has '); + terminal.write(Colors.red(String(highRisk.length))); + terminal.write(' high risk issues and '); + terminal.write(Colors.yellow(String(lowRisk.length))); + terminal.write(' low risk issues\n'); + + if (highRisk.length > 0) { + terminal.writeLine(Colors.red('High risks are')); + for (const risk of highRisk) { + switch (risk.kind) { + case 'readFile': { + terminal.writeLine(`Reads ${risk.filePath}`); + break; + } + case 'writeFile': { + terminal.writeLine(`Writes ${risk.filePath}`); + break; + } + case 'text': { + terminal.writeLine(risk.content); + break; + } + default: { + const _risk: never = risk; + throw new Error(`Unrecognized risk kind: ${(_risk as any).kind}`); + } + } + } + } + }; + + if (checkAllCacheConfiguredProject) { + Object.entries(analyzeResult).forEach(([packageName, result]) => { + writeProjectAnalyzeResult({ + packageName, + result + }); + }); + } else { + for (const projectName of projectNames) { + const targetProjectAnalyzeResult: IAnalyzeResult['key'] = analyzeResult[projectName]; + + writeProjectAnalyzeResult({ + packageName: projectName, + result: targetProjectAnalyzeResult + }); + } + } + + terminal.writeLine(''); + terminal.writeLine(`For more details, you can check ${resultJsonFile}`); + + return { + traceResult, + analyzeResult + }; +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/bin.ts b/rush-plugins/rush-audit-cache-plugin/src/bin.ts new file mode 100644 index 0000000..0df411a --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/bin.ts @@ -0,0 +1,95 @@ +#!/usr/bin/env node +import fs from 'fs'; +import path from 'path'; +import { program } from 'commander'; + +import { terminal, terminalProvider } from './helpers/terminal'; +import { JsonObject } from '@rushstack/node-core-library'; +import { auditCache } from './auditCache'; + +let version: string = ''; +try { + const pkgJson: JsonObject = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8')); + ({ version } = pkgJson); +} catch { + // no-catch +} + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + program + .name('rush-audit-cache') + .version(version) + .option('-p, --project [project...]', 'package name of the target project') + .option('-e, --exclude [exclude...]', 'exclude package from audit cache') + .option('-a, --all', 'audit all cache configured project') + .option( + '-c, --parallelism [parallelism]', + "Specifies the maximum number of concurrent processes to launch during a build. (eg. '50% | '5')" + ) + .option('-P, --phased-commands [phasedCommands...]', 'phased commands need to be audit') + .option('-v, --verbose [verbose]', 'set log level, default is 0, 1 for verbose, 2 for debug') + .action( + async (opts: { + project: string[]; + verbose: string; + all: boolean; + exclude?: string[]; + parallelism?: string; + phasedCommands?: string[]; + }) => { + const checkAllCacheConfiguredProject: boolean = opts.all; + const phasedCommands: string[] = opts.phasedCommands + ? opts.phasedCommands.length + ? opts.phasedCommands + : ['build'] + : ['build']; + const projectNames: string[] = [...new Set(opts.project)]; + if (checkAllCacheConfiguredProject && projectNames.length) { + terminal.writeErrorLine(`The parameters "--all" and "--project" cannot be used together.`); + program.help(); + } + if (!projectNames.length && !checkAllCacheConfiguredProject) { + terminal.writeErrorLine(`The parameters "--all" and "--project" must be passed at least one.`); + program.help(); + } + const verbose: number = +(opts.verbose ?? 0); + if (verbose > 0) { + let cliLevel: string = ''; + switch (verbose) { + case 1: + cliLevel = 'verbose'; + terminalProvider.verboseEnabled = true; + break; + default: + cliLevel = 'debug'; + terminalProvider.verboseEnabled = true; + terminalProvider.debugEnabled = true; + break; + } + console.log(`Log level set to ${cliLevel} by CLI`); + } + await auditCache({ + projectNames, + terminal, + checkAllCacheConfiguredProject, + exclude: opts.exclude ?? [], + parallelism: opts.parallelism, + phasedCommands + }); + } + ); + await program.parseAsync(process.argv); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/Analyzer.ts b/rush-plugins/rush-audit-cache-plugin/src/core/Analyzer.ts new file mode 100644 index 0000000..2740f92 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/Analyzer.ts @@ -0,0 +1,216 @@ +import * as path from 'path'; +import { Colors, IColorableSequence } from '@rushstack/node-core-library'; + +import { getSortedAllDependencyProjects, tryLoadJson } from '../helpers/rushProject'; +import type { + IRushProjectJson, + IAuditCacheFileFilter, + IAuditCacheGlobalFileFilter +} from '../helpers/rushProject'; + +import type { RushConfiguration, RushConfigurationProject } from '@rushstack/rush-sdk'; +import type { ITraceResult } from './base/BaseTraceExecutor'; + +import { ReadFileResolver } from './ReadFileResolver'; +import { WriteFileResolver } from './WriteFileResolver'; +import type { IFileResolveResult } from './base/BaseFileResolver'; + +import { terminal } from '../helpers/terminal'; +import { + RUSH_PROJECT_JSON_RELATIVE_PATH, + RUSH_AUDIT_CACHE_JSON_RELATIVE_PATH, + PLUGIN_NAME +} from '../helpers/constants'; + +export interface IAnalyzerOptions { + rushConfiguration: RushConfiguration; + phasedCommands: string[]; +} + +export type IRisk = IReadFileRisk | IWriteFileRisk | IRiskText; + +export interface IReadFileRisk { + readonly kind: 'readFile'; + filePath: string; +} + +export interface IWriteFileRisk { + readonly kind: 'writeFile'; + filePath: string; +} + +export interface IRiskText { + readonly kind: 'text'; + content: string | IColorableSequence; +} + +export interface IAnalyzeResult { + [packageName: string]: { + lowRisk: IRisk[]; + highRisk: IRisk[]; + }; +} + +export class AuditCacheAnalyzer { + private _rushConfiguration: RushConfiguration; + private _phasedCommands: string[]; + + public constructor(options: IAnalyzerOptions) { + this._rushConfiguration = options.rushConfiguration; + this._phasedCommands = options.phasedCommands; + } + + public analyze(input: ITraceResult): IAnalyzeResult { + // prepare global audit cache config + const pluginOptionsJsonFilePath: string = path.join( + this._rushConfiguration.rushPluginOptionsFolder, + `${PLUGIN_NAME}.json` + ); + + const globalAuditCacheJson: IAuditCacheGlobalFileFilter | undefined = + tryLoadJson(pluginOptionsJsonFilePath); + + const globalFileFilters: IAuditCacheGlobalFileFilter['globalFileFilters'] = + globalAuditCacheJson?.globalFileFilters ?? []; + + terminal.writeLine(`Found ${globalFileFilters.length} filters in ${pluginOptionsJsonFilePath}`); + + return Object.entries(input).reduce((acc, [projectName, { readFiles, writeFiles }]) => { + const project: RushConfigurationProject | undefined = + this._rushConfiguration.getProjectByName(projectName); + + if (!project) { + throw new Error(`no project ${projectName} RushConfigurationProject`); + } + const readFileResolver: ReadFileResolver = new ReadFileResolver(); + const writeFileResolver: WriteFileResolver = new WriteFileResolver(); + + const { projectFolder } = project; + + // get user project rush audit cache config + const rushProjectAuditCacheJsonPath: string = path.join( + projectFolder, + RUSH_AUDIT_CACHE_JSON_RELATIVE_PATH + ); + + const rushProjectAuditCacheJson: IAuditCacheFileFilter | undefined = tryLoadJson( + rushProjectAuditCacheJsonPath + ); + + const fileFilters: IAuditCacheFileFilter['fileFilters'] = rushProjectAuditCacheJson?.fileFilters ?? []; + + terminal.writeLine(`Found ${fileFilters.length} filters in project ${projectName}`); + + // dependency project folders + const allDependencyProjectFolders: string[] = getSortedAllDependencyProjects(project).map( + (p) => p.projectFolder + ); + + readFileResolver.projectSafeMatcher.add([project.projectFolder].concat(allDependencyProjectFolders)); + + const outputFolderNames: string[] = []; + const inputFolderNames: string[] = []; + const rushProjectJsonPath: string = path.join(projectFolder, RUSH_PROJECT_JSON_RELATIVE_PATH); + const rushProjectJson: IRushProjectJson | undefined = + tryLoadJson(rushProjectJsonPath); + + if (rushProjectJson) { + const { operationSettings = [], incrementalBuildIgnoredGlobs = [] } = rushProjectJson; + if (incrementalBuildIgnoredGlobs.length > 0) { + readFileResolver.projectSafeMatcher.add( + incrementalBuildIgnoredGlobs.map((p) => path.join(project.projectFolder, p)) + ); + } + const usedOperationSettings: IRushProjectJson['operationSettings'] | undefined = + operationSettings.filter(({ operationName }) => this._phasedCommands.includes(operationName)); + if (usedOperationSettings && usedOperationSettings.length) { + usedOperationSettings.forEach( + ({ outputFolderNames: outputFolders, dependsOnAdditionalFiles = [] }) => { + outputFolderNames.push(...outputFolders, ...dependsOnAdditionalFiles); + inputFolderNames.push(...dependsOnAdditionalFiles); + } + ); + } + } + writeFileResolver.projectSafeMatcher.add( + outputFolderNames.map((director) => path.join(project.projectFolder, director)) + ); + readFileResolver.projectSafeMatcher.add( + inputFolderNames.map((director) => path.join(project.projectFolder, director)) + ); + + // prepare audit cache global config + readFileResolver.loadGlobalFilterConfig(globalFileFilters); + writeFileResolver.loadGlobalFilterConfig(globalFileFilters); + + // prepare audit cache project config + readFileResolver.loadProjectFilterConfig(fileFilters); + writeFileResolver.loadProjectFilterConfig(fileFilters); + + if (!acc[projectName]) { + acc[projectName] = { + lowRisk: [], + highRisk: [] + }; + } + for (const readFilePath of readFiles) { + terminal.writeDebugLine(`readFilePath: ${readFilePath}`); + const result: IFileResolveResult = readFileResolver.resolve(readFilePath); + terminal.writeDebugLine(`resolve readFilePath result: ${readFilePath} ${JSON.stringify(result)}`); + + if (result.level === 'safe') { + continue; + } + + if (result.level === 'low') { + acc[projectName].lowRisk.push({ + kind: 'readFile', + filePath: readFilePath + }); + continue; + } + + // Otherwise, high risk + acc[projectName].highRisk.push({ + kind: 'readFile', + filePath: readFilePath + }); + } + + if (outputFolderNames.length === 0) { + acc[projectName].highRisk.push({ + kind: 'text', + content: Colors.red( + `"outputFolderNames" are not defined for build operation of project "${projectName}"` + ) + }); + } + + for (const writeFilePath of writeFiles) { + terminal.writeDebugLine(`writeFilePath: ${writeFilePath}`); + const result: IFileResolveResult = writeFileResolver.resolve(writeFilePath); + terminal.writeDebugLine(`resolve writeFilePath result: ${writeFilePath} ${JSON.stringify(result)}`); + + if (result.level === 'safe') { + continue; + } + + if (result.level === 'low') { + acc[projectName].lowRisk.push({ + kind: 'writeFile', + filePath: writeFilePath + }); + continue; + } + + // Otherwise, high risk + acc[projectName].highRisk.push({ + kind: 'writeFile', + filePath: writeFilePath + }); + } + + return acc; + }, {} as IAnalyzeResult); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/Linux/LinuxTraceExecutor.ts b/rush-plugins/rush-audit-cache-plugin/src/core/Linux/LinuxTraceExecutor.ts new file mode 100644 index 0000000..c4b318d --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/Linux/LinuxTraceExecutor.ts @@ -0,0 +1,99 @@ +import * as path from "path"; +import { Executable, FileSystem } from "@rushstack/node-core-library"; + +import { + BaseTraceExecutor, + IBaseTraceExecutorOptions, + ITraceResult, +} from "../base/BaseTraceExecutor"; +import { StraceLogParser } from "./StraceLogParser"; +import { TRACE_LOG_FILENAME } from "../../helpers/constants"; +import { installProjects } from "../../helpers/rushProject"; + +import type { SpawnSyncReturns } from "child_process"; + +export class LinuxTraceExecutor extends BaseTraceExecutor { + private _stracePath: string; + private _straceLogParser: StraceLogParser; + private _straceLogFolderPath: string; + private _parallelism?: string; + + public constructor(options: IBaseTraceExecutorOptions) { + super(options); + + this._parallelism = options.parallelism; + + const stracePath: string | undefined = Executable.tryResolve("strace"); + if (!stracePath) { + throw new Error(`strace is not present.`); + } + this._stracePath = stracePath; + + this._straceLogFolderPath = path.join(this._logFolder, "logs"); + FileSystem.ensureEmptyFolder(this._straceLogFolderPath); + this._straceLogParser = new StraceLogParser({ + projects: options.projects, + logFolder: options.logFolder, + straceLogFolderPath: this._straceLogFolderPath, + }); + } + + public async execAsync(): Promise { + const projectArgs: string[] = this._projects.reduce( + (acc, { packageName }) => { + acc.push("--to"); + acc.push(packageName); + return acc; + }, + [] as string[] + ); + + this._terminal.writeLine(""); + this._terminal.writeLine( + `Running "rush install ${projectArgs.join(" ")}"...` + ); + this._terminal.writeLine(""); + installProjects(this._projects); + + const parallelismArgs: string[] = this._parallelism + ? ["--parallelism", this._parallelism] + : []; + + const args: string[] = [ + "-ff", + "-y", + "-s", + "200", + "-o", + TRACE_LOG_FILENAME, + "-E", + "RUSH_BUILD_CACHE_ENABLED=0", + "rush", + "rebuild", + ...parallelismArgs, + ...projectArgs, + ]; + + this._terminal.writeLine(""); + this._terminal.writeLine(`Running "strace ${args.join(" ")}"...`); + this._terminal.writeLine(""); + + const spawnResult: SpawnSyncReturns = Executable.spawnSync( + this._stracePath, + args, + { + currentWorkingDirectory: this._straceLogFolderPath, + stdio: "inherit", + } + ); + + if (spawnResult.status !== 0) { + throw new Error(`strace failed with exit code ${spawnResult.status}`); + } + + this._terminal.writeLine(""); + this._terminal.writeLine("Parsing strace log start..."); + + return await this._straceLogParser.parseAsync(); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/Linux/StraceLogParser.ts b/rush-plugins/rush-audit-cache-plugin/src/core/Linux/StraceLogParser.ts new file mode 100644 index 0000000..591f204 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/Linux/StraceLogParser.ts @@ -0,0 +1,284 @@ +import * as path from "path"; +import * as fs from "fs"; +import { createInterface, Interface } from "readline"; +import { FileSystem } from "@rushstack/node-core-library"; + +import type { RushConfigurationProject } from "@rushstack/rush-sdk"; +import { ITraceResult } from "../base/BaseTraceExecutor"; +import { TRACE_LOG_FILENAME } from "../../helpers/constants"; +import { terminal } from "../../helpers/terminal"; +import { durationToString } from "../../helpers/utils"; +export interface IStraceLogParserOptions { + projects: RushConfigurationProject[]; + straceLogFolderPath: string; + logFolder: string; +} + +const OPERATION_START_LINE_PREFIX: string = 'chdir("'; +const OPERATION_START_LINE_SUFFIX: string = '") = 0'; +const CHILD_PROCESS_REGEX: RegExp = /^clone\(.+\) = (\d+)$/; +const OPEN_AT_FINISH_REGEX: RegExp = + /^openat\(([A-Z_]+), "(.+)", ([A-Z_|]+)(, [0-9]+)?\) = [0-9]+<(.+)>$/gi; +const OPEN_FINISH_REGEX: RegExp = + /^open\("(.+)", ([A-Z_|]+)(, [0-9]+)?\) = [0-9]+<(.+)>$/gi; +// open("/opt/tiger/tiktok_web_monorepo/packages/libs/tux-h5-color/package.json", O_RDONLY|O_CLOEXEC) = 17 +interface IFileOperateKindResult { + kind: "read" | "write"; + filePath: string; +} + +interface IProjectParseContext { + packageName: string; + started: boolean; + parsedLogFilePath: string; + writeFiles: Set; + readFiles: Set; +} + +export class StraceLogParser { + private _straceLogFolderPath: string; + private _logFolder: string; + private _startLinesToProjectParseContext: Record< + string, + IProjectParseContext + > = {}; + private _pidToProjectParseContext: Record = {}; + private _filePathType: Record = {}; + + public readonly projectParseContextMap: Map; + + public constructor(options: IStraceLogParserOptions) { + this._straceLogFolderPath = options.straceLogFolderPath; + this._logFolder = options.logFolder; + + this.projectParseContextMap = new Map(); + + for (const project of options.projects) { + const parsedLogFilePath: string = path.join( + options.logFolder, + project.packageName, + "strace.log" + ); + FileSystem.deleteFile(parsedLogFilePath); + FileSystem.writeFile(parsedLogFilePath, "", { + ensureFolderExists: true, + }); + const projectParseContext: IProjectParseContext = { + packageName: project.packageName, + started: false, + writeFiles: new Set(), + readFiles: new Set(), + parsedLogFilePath, + }; + this.projectParseContextMap.set(project.packageName, projectParseContext); + + const startLine: string = `${OPERATION_START_LINE_PREFIX}${project.projectFolder}${OPERATION_START_LINE_SUFFIX}`; + this._startLinesToProjectParseContext[startLine] = projectParseContext; + } + } + + public async parseAsync(): Promise { + const startTime: number = Date.now(); + //Warning: This API is now obsolete. + // Use FileSystem.readFolderItemNames() instead. + const allLogs: string[] = FileSystem.readFolder( + this._straceLogFolderPath + ).filter((name) => name.startsWith(`${TRACE_LOG_FILENAME}.`)); + allLogs.sort((nameA, nameB) => { + const pidA: number = +nameA.split(".")[2]; + const pidB: number = +nameB.split(".")[2]; + return pidA - pidB; + }); + + const result: ITraceResult = {}; + + for (const logName of allLogs) { + const pId: string = logName.split(".")[2]; + const straceReadStream: fs.ReadStream = fs.createReadStream( + path.join(this._straceLogFolderPath, logName) + ); + const rl: Interface = createInterface({ + input: straceReadStream, + crlfDelay: Infinity, + }); + + for await (const line of rl) { + this._parseLine(line, pId); + } + + // write result in json files for each projects + for (const projectParseContext of this.projectParseContextMap.values()) { + result[projectParseContext.packageName] = { + writeFiles: projectParseContext.writeFiles, + readFiles: projectParseContext.readFiles, + }; + } + } + + const resultFilePath: string = path.join( + this._logFolder, + "parseResult.json" + ); + + FileSystem.writeFile( + resultFilePath, + JSON.stringify( + result, + (key, value) => { + if (value instanceof Set) { + return Array.from(value); + } + return value; + }, + 2 + ) + ); + const endTime: number = Date.now(); + + const duration: string = durationToString((endTime - startTime) / 1000); + + terminal.writeLine(`Parsing strace log end (${duration})`); + return result; + } + + private _parseLine(line: string, pId: string): void { + if (!pId) { + return; + } + + let projectParseContext: IProjectParseContext | undefined = + this._pidToProjectParseContext[pId]; + + if (!projectParseContext) { + Object.keys(this._startLinesToProjectParseContext).some( + (startLine: string) => { + if ( + line.includes(startLine) && + !this._startLinesToProjectParseContext[startLine].started + ) { + terminal.writeDebugLine(`start line ${startLine}`); + projectParseContext = + this._startLinesToProjectParseContext[startLine]; + // project operation start + projectParseContext.started = true; + this._pidToProjectParseContext[pId] = projectParseContext; + FileSystem.appendToFile( + projectParseContext.parsedLogFilePath, + `${line}\n` + ); + return true; + } + return false; + } + ); + } else { + FileSystem.appendToFile( + projectParseContext.parsedLogFilePath, + `${line}\n` + ); + + // handle fork process + const childProcessId: string | undefined = + this._parseChildProcessId(line); + if (childProcessId) { + this._pidToProjectParseContext[childProcessId] = projectParseContext; + } + + // record read/write files + const fileOperateKindResult: IFileOperateKindResult | undefined = + this._parseFileOperateKind(line); + if (fileOperateKindResult) { + switch (fileOperateKindResult.kind) { + case "read": { + projectParseContext.readFiles.add(fileOperateKindResult.filePath); + break; + } + case "write": { + projectParseContext.writeFiles.add(fileOperateKindResult.filePath); + break; + } + default: { + // no-default + } + } + } + } + } + + private _parseChildProcessId(line: string): string | undefined { + return line.match(CHILD_PROCESS_REGEX)?.[1]; + } + + private _handleFileOperate(params: { + operations: string[]; + filePath: string; + }): IFileOperateKindResult | undefined { + const { operations, filePath } = params; + const kind: IFileOperateKindResult["kind"] | null = operations.find( + (operation) => operation === "O_DIRECTORY" + ) + ? null + : operations.find((operation) => operation === "O_RDONLY") + ? "read" + : operations.find((operation) => operation === "O_WRONLY") + ? "write" + : null; + if (!kind) { + return; + } + try { + const fileType: "file" | "director" | "no_exist" = + this._filePathType[filePath]; + if (fileType === "director") { + return; + } + if (!fileType) { + this._filePathType[filePath] = "file"; + + if (fs.statSync(filePath).isDirectory()) { + this._filePathType[filePath] = "director"; + return; + } + } + } catch (e) { + this._filePathType[filePath] = "no_exist"; + } + + return { + kind, + filePath, + }; + } + + private _parseFileOperateKind( + line: string + ): IFileOperateKindResult | undefined { + const parseOpenLineResult: RegExpExecArray | null = + OPEN_FINISH_REGEX.exec(line); + if (parseOpenLineResult?.length) { + terminal.writeDebugLine( + `parseOpenLineResult ${JSON.stringify(parseOpenLineResult)}` + ); + const operations: string[] = parseOpenLineResult[2].split("|"); + return this._handleFileOperate({ + operations, + filePath: parseOpenLineResult[4] ?? parseOpenLineResult[1], + }); + } + + const parseOpenAtLineResult: RegExpExecArray | null = + OPEN_AT_FINISH_REGEX.exec(line); + if (parseOpenAtLineResult?.length) { + terminal.writeDebugLine( + `parseOpenAtLineResult ${JSON.stringify(parseOpenAtLineResult)}` + ); + const operations: string[] = parseOpenAtLineResult[3].split("|"); + return this._handleFileOperate({ + operations, + filePath: parseOpenAtLineResult[5] ?? parseOpenAtLineResult[2], + }); + } + + return; + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/ReadFileResolver.ts b/rush-plugins/rush-audit-cache-plugin/src/core/ReadFileResolver.ts new file mode 100644 index 0000000..68c96fa --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/ReadFileResolver.ts @@ -0,0 +1,101 @@ +import ignore, { Ignore } from "ignore"; +import { BaseFileResolver } from "./base/BaseFileResolver"; +import type { + IUserProjectFileFilter, + IUserProjectAfterFileFilter, +} from "./base/BaseFileResolver"; + +export class ReadFileResolver extends BaseFileResolver { + private _lowRiskSystemRead: string[] = [ + "/usr/lib/", + "/usr/share/locale/", + "/usr/share/zoneinfo/", + "/lib/", + "/etc/", + "/sys/", + "/proc/", + "/dev/null", + "/dev/null/", + ]; + private _lowRiskSystemReadMatcher: Ignore = ignore(); + private _lowRiskNodeRead: string[] = [ + "**/.nvm/", + "**/.npm/", + "**/node_modules/npm/", + "**/node_modules/pnpm/", + "**/node_modules/.cache/", + "**/node_modules/.pnpm/", + "**/.pnpm/", + "**/.npmrc", + "**/.nvmrc", + "**/update-notifier-npm.json*", + ]; + private _lowRiskNodeReadMatcher: Ignore = ignore(); + private _lowRiskToolRead: string[] = ["**/.git/", "**/.gitconfig"]; + private _lowRiskToolReadMatcher: Ignore = ignore(); + private _safeToolRead: string[] = ["**/common/temp/node_modules/"]; + private _safeToolReadIgnoreMatcher: Ignore = ignore(); + + public constructor() { + super(); + this.initDefaultMatchers([ + { + matcher: this._lowRiskSystemReadMatcher, + paths: this._lowRiskSystemRead, + option: { + kind: "system", + }, + }, + { + matcher: this._lowRiskNodeReadMatcher, + paths: this._lowRiskNodeRead, + option: { + kind: "node", + }, + }, + { + matcher: this._lowRiskToolReadMatcher, + paths: this._lowRiskToolRead, + option: { + kind: "tool", + }, + }, + { + matcher: this._safeToolReadIgnoreMatcher, + paths: this._safeToolRead, + option: { + kind: "tool", + level: "safe", + }, + }, + ]); + } + + public loadProjectFilterConfig(fileFilters: IUserProjectFileFilter[]): void { + fileFilters.forEach((fileFilter) => { + if (fileFilter.operate === "read") { + if ("kind" in fileFilter) { + this._userProjectAfterFileFilters.unshift( + fileFilter as IUserProjectAfterFileFilter + ); + } else { + this._userProjectBeforeFileFilters.unshift(fileFilter); + } + } + }); + } + + public loadGlobalFilterConfig(fileFilters: IUserProjectFileFilter[]): void { + fileFilters.forEach((fileFilter) => { + if (fileFilter.operate === "read") { + if ("kind" in fileFilter) { + this._userProjectAfterFileFilters.push( + fileFilter as IUserProjectAfterFileFilter + ); + } else { + this._userProjectBeforeFileFilters.push(fileFilter); + } + } + }); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/TraceExecutor.ts b/rush-plugins/rush-audit-cache-plugin/src/core/TraceExecutor.ts new file mode 100644 index 0000000..482e86f --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/TraceExecutor.ts @@ -0,0 +1,23 @@ +import { BaseTraceExecutor, IBaseTraceExecutorOptions } from "./base/BaseTraceExecutor"; +import * as os from 'os'; +import { Import } from "@rushstack/node-core-library"; + +const LinuxTraceExecutorModule: typeof import('./Linux/LinuxTraceExecutor') = Import.lazy("./Linux/LinuxTraceExecutor", require); + +export class TraceExecutorFactory { + + private constructor() { } + + public static create(options: IBaseTraceExecutorOptions): BaseTraceExecutor { + const platform: NodeJS.Platform = os.platform(); + switch (platform) { + case 'linux': { + return new LinuxTraceExecutorModule.LinuxTraceExecutor(options); + } + default: { + throw new Error(`Unsupported OS platform: ${platform}, only linux is supported now.`); + } + } + } + +} \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/WriteFileResolver.ts b/rush-plugins/rush-audit-cache-plugin/src/core/WriteFileResolver.ts new file mode 100644 index 0000000..3190070 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/WriteFileResolver.ts @@ -0,0 +1,66 @@ +import ignore, { Ignore } from "ignore"; +import { BaseFileResolver } from "./base/BaseFileResolver"; +import type { + IUserProjectAfterFileFilter, + IUserProjectFileFilter, +} from "./base/BaseFileResolver"; + +export class WriteFileResolver extends BaseFileResolver { + private _lowRiskNodeWrite: string[] = [ + "**/update-notifier-npm.json*", + "**/node_modules/.cache/", + "**/node_modules/.pnpm/", + ]; + private _lowRiskNodeWriteMatcher: Ignore = ignore(); + + private _lowRiskSystemWrite: string[] = ["/dev/null", "/dev/null/"]; + private _lowRiskSystemWriteMatcher: Ignore = ignore(); + + public constructor() { + super(); + this.initDefaultMatchers([ + { + matcher: this._lowRiskNodeWriteMatcher, + paths: this._lowRiskNodeWrite, + option: { + kind: "node", + }, + }, + { + matcher: this._lowRiskSystemWriteMatcher, + paths: this._lowRiskSystemWrite, + option: { + kind: "system", + }, + }, + ]); + } + + public loadProjectFilterConfig(fileFilters: IUserProjectFileFilter[]): void { + fileFilters.forEach((fileFilter) => { + if (fileFilter.operate === "write") { + if ("kind" in fileFilter) { + this._userProjectAfterFileFilters.unshift( + fileFilter as IUserProjectAfterFileFilter + ); + } else { + this._userProjectBeforeFileFilters.unshift(fileFilter); + } + } + }); + } + + public loadGlobalFilterConfig(fileFilters: IUserProjectFileFilter[]): void { + fileFilters.forEach((fileFilter) => { + if (fileFilter.operate === "write") { + if ("kind" in fileFilter) { + this._userProjectAfterFileFilters.push( + fileFilter as IUserProjectAfterFileFilter + ); + } else { + this._userProjectBeforeFileFilters.push(fileFilter); + } + } + }); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseFileResolver.ts b/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseFileResolver.ts new file mode 100644 index 0000000..6b8c794 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseFileResolver.ts @@ -0,0 +1,132 @@ +import * as path from "path"; +import ignore, { Ignore } from "ignore"; + +export type IResolveKind = "system" | "node" | "tool" | "project"; +export interface IFileResolveResult { + level: "low" | "high" | "safe"; + kind?: IResolveKind; +} + +type OneOf = { + [K in P]-?: Required> & Partial, never>>; +}[P]; + +export type IUserProjectFileFilter = { + level: IFileResolveResult["level"]; + operate: "write" | "read"; +} & OneOf<{ + kind: IResolveKind; + pattern: string | RegExp; +}>; + +export interface IUserProjectBeforeFileFilter { + level: IFileResolveResult["level"]; + operate: "write" | "read"; + pattern: string | RegExp; +} + +export interface IUserProjectAfterFileFilter { + level: IFileResolveResult["level"]; + operate: "write" | "read"; + kind: IResolveKind; +} + +export class BaseFileResolver { + protected _userProjectBeforeFileFilters: IUserProjectBeforeFileFilter[] = []; + protected _userProjectAfterFileFilters: IUserProjectAfterFileFilter[] = []; + + private _matcherToResult: Map = new Map(); + + public projectSafeMatcher: Ignore = ignore(); + + protected constructor() {} + + private _applyUserBeforeFilter( + filePath: string + ): IFileResolveResult | undefined { + for (const fileFilter of this._userProjectBeforeFileFilters) { + if ( + fileFilter.pattern && + new RegExp(fileFilter.pattern, "g").test(filePath) + ) { + return { + level: fileFilter.level, + }; + } + } + return; + } + + private _applyUserAfterFilter( + originMatcherResult: IFileResolveResult + ): IFileResolveResult { + const matcherResult: IFileResolveResult = { + ...originMatcherResult, + }; + for (const fileFilter of this._userProjectAfterFileFilters) { + if (matcherResult.kind === fileFilter.kind) { + matcherResult.level = fileFilter.level; + } + + break; + } + return matcherResult; + } + + protected initDefaultMatchers( + params: { + matcher: Ignore; + paths: string[]; + option: { + kind?: IResolveKind; + level?: "low" | "high" | "safe"; + }; + }[] + ): void { + params.forEach(({ matcher, option, paths }) => { + const { kind, level = "low" } = option; + matcher.add(paths); + this.setMatcher(matcher, { + kind, + level, + }); + }); + } + + public setMatcher(matcher: Ignore, result: IFileResolveResult): void { + this._matcherToResult.set(matcher, result); + } + + public resolve(filePath: string): IFileResolveResult { + const result: IFileResolveResult | undefined = + this._applyUserBeforeFilter(filePath); + if (result) { + return result; + } + + const relativePathToRoot: string = path.relative("/", filePath); + if (!ignore.isPathValid(relativePathToRoot)) { + throw new Error(`wrong path ${relativePathToRoot}`); + } + + if (this.projectSafeMatcher.ignores(relativePathToRoot)) { + return this._applyUserAfterFilter({ level: "safe", kind: "project" }); + } + + const ignored: Ignore | undefined = [...this._matcherToResult.keys()].find( + (ig) => ig.ignores(relativePathToRoot) + ); + + if (ignored) { + const matcherResult: IFileResolveResult = this._matcherToResult.get( + ignored + ) as IFileResolveResult; + + return this._applyUserAfterFilter(matcherResult); + } + + return { + level: "high", + }; + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseTraceExecutor.ts b/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseTraceExecutor.ts new file mode 100644 index 0000000..10cf986 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/base/BaseTraceExecutor.ts @@ -0,0 +1,29 @@ +import type { ITerminal } from "@rushstack/node-core-library"; +import type { RushConfigurationProject } from "@rushstack/rush-sdk"; + +export interface IBaseTraceExecutorOptions { + projects: RushConfigurationProject[]; + logFolder: string; + terminal: ITerminal; + parallelism?: string; +} + +export interface ITraceResult { + [packageName: string]: { + readFiles: ReadonlySet; + writeFiles: ReadonlySet; + }; +} + +export abstract class BaseTraceExecutor { + protected _projects: RushConfigurationProject[]; + protected _logFolder: string; + protected _terminal: ITerminal; + public constructor(options: IBaseTraceExecutorOptions) { + this._projects = options.projects; + this._logFolder = options.logFolder; + this._terminal = options.terminal; + } + + abstract execAsync(): Promise; +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/test/ReadFileResolver.test.ts b/rush-plugins/rush-audit-cache-plugin/src/core/test/ReadFileResolver.test.ts new file mode 100644 index 0000000..076a7cb --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/test/ReadFileResolver.test.ts @@ -0,0 +1,232 @@ +import { ReadFileResolver } from "../ReadFileResolver"; +import { IAnalyzeResult, IRisk } from "../Analyzer"; +import { IFileResolveResult } from "../base/BaseFileResolver"; + +type IAnalyzeResultWithSafe = IAnalyzeResult[string] & { safe: IRisk[] }; + +describe("ReadFileResolver", () => { + const handleResolveResult = ( + result: IAnalyzeResultWithSafe, + resolveResult: IFileResolveResult, + readFilePath: string + ): void => { + if (resolveResult.level === "safe") { + result.safe.push({ + kind: "readFile", + filePath: readFilePath, + }); + return; + } + + if (resolveResult.level === "low") { + result.lowRisk.push({ + kind: "readFile", + filePath: readFilePath, + }); + return; + } + result.highRisk.push({ + kind: "readFile", + filePath: readFilePath, + }); + }; + + it("should audit 1 high risk and 2 low risk", async () => { + const readFiles = [ + "/tmp/rollup-plugin-progress", + "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + ]; + const readFileResolver = new ReadFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + for (const readFilePath of readFiles) { + const resolveResult: IFileResolveResult = + readFileResolver.resolve(readFilePath); + handleResolveResult(result, resolveResult, readFilePath); + } + + expect(result).toEqual({ + lowRisk: [ + { + filePath: "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + kind: "readFile", + }, + { + filePath: + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "readFile", + }, + ], + highRisk: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "readFile", + }, + ], + safe: [], + }); + }); + + it("should audit 2 safe file read", async () => { + const readFiles = [ + "/tmp/rollup-plugin-progress", + "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/src/utils/types.ts", + "/workspaceRepo/a/src/utils/uid.ts", + ]; + const readFileResolver = new ReadFileResolver(); + const result: string[] = []; + + readFileResolver.projectSafeMatcher.add("/workspaceRepo/a"); + + for (const readFilePath of readFiles) { + const resolveResult: IFileResolveResult = + readFileResolver.resolve(readFilePath); + if (resolveResult.level === "safe") { + result.push(readFilePath); + } + } + + expect(result).toEqual([ + "/workspaceRepo/a/src/utils/types.ts", + "/workspaceRepo/a/src/utils/uid.ts", + ]); + }); + + it("should load global config, audit 1 high risk, 2 low risk and 2 safe file read", async () => { + const readFiles = [ + "/tmp/rollup-plugin-progress", + "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/src/utils/types.ts", + "/workspaceRepo/a/src/utils/uid.ts", + ]; + const readFileResolver = new ReadFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + readFileResolver.projectSafeMatcher.add("/workspaceRepo/a"); + readFileResolver.loadGlobalFilterConfig([ + { operate: "read", kind: "system", level: "high" }, + { + operate: "read", + pattern: "^/tmp/rollup-plugin-progress$", + level: "low", + }, + ]); + + for (const readFilePath of readFiles) { + const resolveResult: IFileResolveResult = + readFileResolver.resolve(readFilePath); + handleResolveResult(result, resolveResult, readFilePath); + } + + expect(result).toEqual({ + lowRisk: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "readFile", + }, + { + filePath: + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "readFile", + }, + ], + highRisk: [ + { + filePath: "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + kind: "readFile", + }, + ], + safe: [ + { + filePath: "/workspaceRepo/a/src/utils/types.ts", + kind: "readFile", + }, + { + filePath: "/workspaceRepo/a/src/utils/uid.ts", + kind: "readFile", + }, + ], + }); + }); + + it("should load project and repo config, audit 0 high risk, 1 low risk and 4 safe file read", async () => { + const readFiles = [ + "/tmp/rollup-plugin-progress", + "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/src/utils/types.ts", + "/workspaceRepo/a/src/utils/uid.ts", + ]; + const readFileResolver = new ReadFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + readFileResolver.projectSafeMatcher.add("/workspaceRepo/a"); + readFileResolver.loadGlobalFilterConfig([ + { operate: "read", kind: "system", level: "high" }, + { + operate: "read", + pattern: "^/tmp/rollup-plugin-progress$", + level: "low", + }, + ]); + readFileResolver.loadProjectFilterConfig([ + { operate: "read", kind: "system", level: "safe" }, + { + operate: "read", + pattern: "^/tmp/rollup-plugin-progress$", + level: "safe", + }, + ]); + + for (const readFilePath of readFiles) { + const resolveResult: IFileResolveResult = + readFileResolver.resolve(readFilePath); + handleResolveResult(result, resolveResult, readFilePath); + } + + expect(result).toEqual({ + lowRisk: [ + { + filePath: + "/root/node_modules/.pnpm/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "readFile", + }, + ], + highRisk: [], + safe: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "readFile", + }, + { + filePath: "/usr/lib/x86_64-linux-gnu/libm-2.28.so", + kind: "readFile", + }, + { + filePath: "/workspaceRepo/a/src/utils/types.ts", + kind: "readFile", + }, + { + filePath: "/workspaceRepo/a/src/utils/uid.ts", + kind: "readFile", + }, + ], + }); + }); +}); diff --git a/rush-plugins/rush-audit-cache-plugin/src/core/test/WriteFileResolver.test.ts b/rush-plugins/rush-audit-cache-plugin/src/core/test/WriteFileResolver.test.ts new file mode 100644 index 0000000..69a006e --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/core/test/WriteFileResolver.test.ts @@ -0,0 +1,226 @@ +import { WriteFileResolver } from "../WriteFileResolver"; +import { IAnalyzeResult, IRisk } from "../Analyzer"; +import { IFileResolveResult } from "../base/BaseFileResolver"; + +type IAnalyzeResultWithSafe = IAnalyzeResult[string] & { safe: IRisk[] }; + +describe("WriteFileResolver", () => { + const handleResolveResult = ( + result: IAnalyzeResultWithSafe, + resolveResult: IFileResolveResult, + writeFilePath: string + ): void => { + if (resolveResult.level === "safe") { + result.safe.push({ + kind: "writeFile", + filePath: writeFilePath, + }); + return; + } + + if (resolveResult.level === "low") { + result.lowRisk.push({ + kind: "writeFile", + filePath: writeFilePath, + }); + return; + } + result.highRisk.push({ + kind: "writeFile", + filePath: writeFilePath, + }); + }; + + it("should audit 1 high risk and 2 low risk", async () => { + const writeFiles = [ + "/tmp/rollup-plugin-progress", + "/dev/null", + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + ]; + const writeFileResolver = new WriteFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + for (const writeFilePath of writeFiles) { + const resolveResult: IFileResolveResult = + writeFileResolver.resolve(writeFilePath); + handleResolveResult(result, resolveResult, writeFilePath); + } + + expect(result).toEqual({ + lowRisk: [ + { + filePath: "/dev/null", + kind: "writeFile", + }, + { + filePath: + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "writeFile", + }, + ], + highRisk: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "writeFile", + }, + ], + safe: [], + }); + }); + + it("should audit 2 safe file write", async () => { + const writeFiles = [ + "/tmp/rollup-plugin-progress", + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/dist/src/utils/types.js", + "/workspaceRepo/a/dist/src/utils/uid.js", + "/workspaceRepo/a/example/icons/index.js", + ]; + const writeFileResolver = new WriteFileResolver(); + const result: string[] = []; + + writeFileResolver.projectSafeMatcher.add([ + "/workspaceRepo/a/dist", + "/workspaceRepo/a/example/icons", + ]); + + for (const writeFilePath of writeFiles) { + const resolveResult: IFileResolveResult = + writeFileResolver.resolve(writeFilePath); + if (resolveResult.level === "safe") { + result.push(writeFilePath); + } + } + + expect(result).toEqual([ + "/workspaceRepo/a/dist/src/utils/types.js", + "/workspaceRepo/a/dist/src/utils/uid.js", + "/workspaceRepo/a/example/icons/index.js", + ]); + }); + + it("should load global config, audit 1 high risk, 1 low risk and 2 safe file read", async () => { + const writeFiles = [ + "/tmp/rollup-plugin-progress", + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/dist/src/utils/types.js", + "/workspaceRepo/a/dist/src/utils/uid.js", + ]; + const writeFileResolver = new WriteFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + writeFileResolver.projectSafeMatcher.add("/workspaceRepo/a/dist"); + writeFileResolver.loadGlobalFilterConfig([ + { operate: "write", kind: "node", level: "high" }, + { + operate: "write", + pattern: "^/tmp/rollup-plugin-progress$", + level: "low", + }, + ]); + + for (const writeFilePath of writeFiles) { + const resolveResult: IFileResolveResult = + writeFileResolver.resolve(writeFilePath); + handleResolveResult(result, resolveResult, writeFilePath); + } + + expect(result).toEqual({ + lowRisk: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "writeFile", + }, + ], + highRisk: [ + { + filePath: + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "writeFile", + }, + ], + safe: [ + { + filePath: "/workspaceRepo/a/dist/src/utils/types.js", + kind: "writeFile", + }, + { + filePath: "/workspaceRepo/a/dist/src/utils/uid.js", + kind: "writeFile", + }, + ], + }); + }); + + it("should load project and repo config, audit 0 high risk, 1 low risk and 3 safe file read", async () => { + const writeFiles = [ + "/tmp/rollup-plugin-progress", + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + "/workspaceRepo/a/dist/src/utils/types.js", + "/workspaceRepo/a/dist/src/utils/uid.js", + ]; + const writeFileResolver = new WriteFileResolver(); + const result: IAnalyzeResultWithSafe = { + lowRisk: [], + highRisk: [], + safe: [], + }; + + writeFileResolver.projectSafeMatcher.add("/workspaceRepo/a/dist"); + writeFileResolver.loadGlobalFilterConfig([ + { operate: "write", kind: "node", level: "high" }, + { + operate: "write", + pattern: "^/tmp/rollup-plugin-progress$", + level: "low", + }, + ]); + writeFileResolver.loadProjectFilterConfig([ + { operate: "write", kind: "node", level: "low" }, + { + operate: "write", + pattern: "^/tmp/rollup-plugin-progress$", + level: "safe", + }, + ]); + + for (const writeFilePath of writeFiles) { + const resolveResult: IFileResolveResult = + writeFileResolver.resolve(writeFilePath); + handleResolveResult(result, resolveResult, writeFilePath); + } + + expect(result).toEqual({ + highRisk: [], + lowRisk: [ + { + filePath: + "/root/node_modules/.cache/rollup-plugin-typescript2/umd/rpt2_ce91b375290c4fee5b255c9d9f687d89e0587857/code/cache/435d89aa78", + kind: "writeFile", + }, + ], + safe: [ + { + filePath: "/tmp/rollup-plugin-progress", + kind: "writeFile", + }, + { + filePath: "/workspaceRepo/a/dist/src/utils/types.js", + kind: "writeFile", + }, + { + filePath: "/workspaceRepo/a/dist/src/utils/uid.js", + kind: "writeFile", + }, + ], + }); + }); +}); diff --git a/rush-plugins/rush-audit-cache-plugin/src/helpers/constants.ts b/rush-plugins/rush-audit-cache-plugin/src/helpers/constants.ts new file mode 100644 index 0000000..43eeef5 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/helpers/constants.ts @@ -0,0 +1,8 @@ +export const AUDIT_CACHE_FOLDER: string = "rush-audit-cache"; +export const TRACE_LOG_FILENAME: string = "trace.log"; +export const RUSH_PROJECT_JSON_RELATIVE_PATH: string = + "./config/rush-project.json"; +export const RUSH_AUDIT_CACHE_JSON_RELATIVE_PATH: string = + "./config/rush-audit-cache.json"; + +export const PLUGIN_NAME: string = "rush-audit-cache-plugin"; diff --git a/rush-plugins/rush-audit-cache-plugin/src/helpers/rushProject.ts b/rush-plugins/rush-audit-cache-plugin/src/helpers/rushProject.ts new file mode 100644 index 0000000..9ec030c --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/helpers/rushProject.ts @@ -0,0 +1,132 @@ +import * as path from 'path'; +import { Executable } from '@rushstack/node-core-library'; + +import { RushConfiguration, RushConfigurationProject } from '@rushstack/rush-sdk'; +import { FileSystem, JsonFile } from '@rushstack/node-core-library'; + +import { RUSH_PROJECT_JSON_RELATIVE_PATH } from './constants'; + +import type { IUserProjectFileFilter } from '../core/base/BaseFileResolver'; +import type { SpawnSyncReturns } from 'child_process'; + +export interface IRushProjectJson { + operationSettings: { + operationName: string; + outputFolderNames: string[]; + dependsOnAdditionalFiles?: string[]; + }[]; + incrementalBuildIgnoredGlobs: string[]; +} + +export interface IAuditCacheFileFilter { + fileFilters: IUserProjectFileFilter[]; +} + +export interface IAuditCacheGlobalFileFilter { + globalFileFilters: IUserProjectFileFilter[]; +} + +const packageNameToAllDependencyProjects: Record = {}; + +/** + * Get all dependency projects of a project both directly and indirectly, + * and topologically sort them at the same time. + */ +export const getSortedAllDependencyProjects = ( + project: RushConfigurationProject +): ReadonlyArray => { + let allDependencyProjects: RushConfigurationProject[] | undefined = + packageNameToAllDependencyProjects[project.packageName]; + if (!allDependencyProjects) { + const visited: Set = new Set(); + allDependencyProjects = []; + + for (const dependency of project.dependencyProjects) { + if (visited.has(dependency.packageName)) { + continue; + } + recursiveGetAndSortAllDependencyProjects(project, visited, allDependencyProjects); + } + + packageNameToAllDependencyProjects[project.packageName] = allDependencyProjects; + } + return allDependencyProjects; +}; + +/** + * recursively walk through all dependency projects of a project, + */ +function recursiveGetAndSortAllDependencyProjects( + project: RushConfigurationProject, + visited: Set, + allDependencyProjects: RushConfigurationProject[] +): void { + visited.add(project.packageName); + for (const dependency of project.dependencyProjects) { + if (visited.has(dependency.packageName)) { + continue; + } + recursiveGetAndSortAllDependencyProjects(dependency, visited, allDependencyProjects); + } + allDependencyProjects.push(project); +} + +/** + * try to load json by path + */ +export function tryLoadJson(jsonFilePath: string): T | undefined { + try { + const loadedJson: T = JsonFile.load(jsonFilePath); + return loadedJson; + } catch (e) { + if (FileSystem.isFileDoesNotExistError(e as Error)) { + return; + } else { + throw e; + } + } +} + +/** + * get all build cache configured project + */ +export function getAllCacheConfiguredProjects( + rushConfiguration: RushConfiguration +): RushConfigurationProject[] { + const projects: RushConfigurationProject[] = rushConfiguration.projects; + return projects.filter((project) => { + const rushProjectJsonPath: string = path.join(project.projectFolder, RUSH_PROJECT_JSON_RELATIVE_PATH); + + const rushProjectJson: IRushProjectJson | undefined = tryLoadJson(rushProjectJsonPath); + if (!rushProjectJson) { + return false; + } + const { operationSettings = [] } = rushProjectJson; + return Boolean(operationSettings.length); + }); +} + +/** + * install projects + */ +export function installProjects(projects: RushConfigurationProject[]): void { + const rushPath: string | undefined = Executable.tryResolve('rush'); + if (!rushPath) { + throw new Error(`rush is not present.`); + } + const projectArgs: string[] = projects.reduce((acc, { packageName }) => { + acc.push('--to'); + acc.push(packageName); + return acc; + }, [] as string[]); + + const args: string[] = ['install', ...projectArgs]; + + const spawnResult: SpawnSyncReturns = Executable.spawnSync(rushPath, args, { + stdio: 'inherit' + }); + + if (spawnResult.status !== 0) { + throw new Error(`rush install failed with exit code ${spawnResult.status}`); + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/src/helpers/terminal.ts b/rush-plugins/rush-audit-cache-plugin/src/helpers/terminal.ts new file mode 100644 index 0000000..f7f8d39 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/helpers/terminal.ts @@ -0,0 +1,7 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; + +export const terminalProvider: ConsoleTerminalProvider = new ConsoleTerminalProvider(); +export const terminal: Terminal = new Terminal(terminalProvider); diff --git a/rush-plugins/rush-audit-cache-plugin/src/helpers/utils.ts b/rush-plugins/rush-audit-cache-plugin/src/helpers/utils.ts new file mode 100644 index 0000000..23fe9e9 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/helpers/utils.ts @@ -0,0 +1,12 @@ +export const durationToString = (duration: number): string => { + if (duration > 60) { + const minutes: number = Math.floor(duration / 60); + const seconds: number = duration % 60.0; + + return `${minutes.toFixed(0)} minute${ + minutes === 1 ? "" : "s" + } ${seconds.toFixed(1)} seconds`; + } else { + return `${duration.toFixed(2)} seconds`; + } +}; diff --git a/rush-plugins/rush-audit-cache-plugin/src/index.ts b/rush-plugins/rush-audit-cache-plugin/src/index.ts new file mode 100644 index 0000000..ebc798f --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/index.ts @@ -0,0 +1,3 @@ +export { auditCache } from './auditCache'; + +export type { IAuditCacheOptions, IAuditCacheResult } from './auditCache'; \ No newline at end of file diff --git a/rush-plugins/rush-audit-cache-plugin/src/schemas/plugin-options.schema.json b/rush-plugins/rush-audit-cache-plugin/src/schemas/plugin-options.schema.json new file mode 100644 index 0000000..cb390e7 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/src/schemas/plugin-options.schema.json @@ -0,0 +1,69 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Configuration for Rush's build cache.", + "description": "For use with the Rush tool, this file provides per-project configuration options. See http://rushjs.io for details.", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.", + "type": "string" + }, + "extends": { + "description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.", + "type": "string" + }, + "globalFileFilters": { + "type": "array", + "description": "Defines overrides for file operate level for kind or path. Through this setting you can hide specific file or give them a more important visibility.", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "level": { + "type": "string", + "enum": ["low", "high", "safe"], + "description": "The risk level of file operate" + }, + "operate": { + "type": "string", + "enum": ["read", "write"], + "description": "The operate of file access" + }, + "kind": { + "type": "string", + "enums": ["system", "node", "tool", "project"], + "description": "The kind of file" + }, + "pattern": { + "type": "string", + "description": "Use RegExp to match file path" + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "enums": ["system", "node", "tool", "project"], + "description": "The kind of file" + } + }, + "required": ["kind"] + }, + { + "type": "object", + "properties": { + "pattern": { + "type": "string", + "description": "Use RegExp to match file path" + } + }, + "required": ["pattern"] + } + ] + } + } + } +} diff --git a/rush-plugins/rush-audit-cache-plugin/tsconfig.json b/rush-plugins/rush-audit-cache-plugin/tsconfig.json new file mode 100644 index 0000000..82917d2 --- /dev/null +++ b/rush-plugins/rush-audit-cache-plugin/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-git-lfs-plugin/.eslintrc.js b/rush-plugins/rush-git-lfs-plugin/.eslintrc.js new file mode 100644 index 0000000..c9d48bd --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require('@rushstack/eslint-config/patch/modern-module-resolution'); + +module.exports = { + extends: [ + '@rushstack/eslint-config/profile/node-trusted-tool', + '@rushstack/eslint-config/mixins/friendly-locals', + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ['node_modules/', 'lib/', 'jest.config.js'], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/rush-plugins/rush-git-lfs-plugin/.gitignore b/rush-plugins/rush-git-lfs-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/.npmignore b/rush-plugins/rush-git-lfs-plugin/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-git-lfs-plugin/CHANGELOG.json b/rush-plugins/rush-git-lfs-plugin/CHANGELOG.json new file mode 100644 index 0000000..7f75af3 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/CHANGELOG.json @@ -0,0 +1,53 @@ +{ + "name": "rush-git-lfs-plugin", + "entries": [ + { + "version": "0.2.0", + "tag": "rush-git-lfs-plugin_v0.2.0", + "date": "Tue, 14 Feb 2023 03:16:01 GMT", + "comments": { + "minor": [ + { + "comment": "add git lfs pull plugin" + } + ] + } + }, + { + "version": "0.1.2", + "tag": "rush-git-lfs-plugin_v0.1.2", + "date": "Wed, 08 Feb 2023 07:35:21 GMT", + "comments": { + "patch": [ + { + "comment": "Reduce log and use ora as alternative" + } + ] + } + }, + { + "version": "0.1.1", + "tag": "rush-git-lfs-plugin_v0.1.1", + "date": "Mon, 19 Dec 2022 11:19:35 GMT", + "comments": { + "patch": [ + { + "comment": "fix rush-git-lfs-plugin configuration and wrong constant" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-git-lfs-plugin_v0.1.0", + "date": "Fri, 16 Dec 2022 12:24:06 GMT", + "comments": { + "minor": [ + { + "comment": "Add new plugin rush-git-lfs-plugin to support git-lfs check." + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-git-lfs-plugin/CHANGELOG.md b/rush-plugins/rush-git-lfs-plugin/CHANGELOG.md new file mode 100644 index 0000000..7074521 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/CHANGELOG.md @@ -0,0 +1,32 @@ +# Change Log - rush-git-lfs-plugin + +This log was last generated on Tue, 14 Feb 2023 03:16:01 GMT and should not be manually modified. + +## 0.2.0 +Tue, 14 Feb 2023 03:16:01 GMT + +### Minor changes + +- add git lfs pull plugin + +## 0.1.2 +Wed, 08 Feb 2023 07:35:21 GMT + +### Patches + +- Reduce log and use ora as alternative + +## 0.1.1 +Mon, 19 Dec 2022 11:19:35 GMT + +### Patches + +- fix rush-git-lfs-plugin configuration and wrong constant + +## 0.1.0 +Fri, 16 Dec 2022 12:24:06 GMT + +### Minor changes + +- Add new plugin rush-git-lfs-plugin to support git-lfs check. + diff --git a/rush-plugins/rush-git-lfs-plugin/LICENSE b/rush-plugins/rush-git-lfs-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-git-lfs-plugin/README.md b/rush-plugins/rush-git-lfs-plugin/README.md new file mode 100644 index 0000000..ba2c8c2 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/README.md @@ -0,0 +1,85 @@ +# rush-git-lfs-plugin + +A rush plugin that can check if files are correctly managed by Git LFS. + +# Prerequisite + +Rush.js >= 5.83.2 + + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +1. Running `git-lfs-check` command + +```bash +# auto detect changed files by "git diff" +rush git-lfs-check + +# or you can specify the files that need to be check\ +rush git-lfs-check --file + +# you can add --fix option to auto fix incorrect lfs status +``` +# Configuration + +You can specify which paths should be checked by provided a set of glob patterns and the size threshold can be customized. + +**JSON Schema For configuration** +```json5 +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Configuration for Rush Git LFS plugin", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "default": "http://json-schema.org/draft-04/schema#" + }, + "checkPattern": { + "description": "Glob patterns that need to check", + "patternProperties": { + "^.+$": { + "type": "string", + "description": "Customized size threshold for this pattern." + } + } + }, + "errorTips": { + "type": "string", + "description": "Tips that shown while there are check errors" + } + } +} +``` + +## Example Configurations +* Ban all png and dll files + ```json5 + { + "checkPattern": { + "**/*.png": -1, + "**/*.dll": -1 + }, + } + ``` +* Ban all files that larger than 5MB + ```json5 + { + "checkPattern": { + "**/*": 5 * 1024 * 124, + }, + } + ``` +* Ban files in particular folder + ```json5 + { + "checkPattern": { + "**/some_folder_path": -1, + }, + } + ``` \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/command-line.json b/rush-plugins/rush-git-lfs-plugin/command-line.json new file mode 100644 index 0000000..ad372cf --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/command-line.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "git-lfs-check", + "commandKind": "global", + "summary": "Check Git LFS file in rush project", + "shellCommand": "node /lib/bin.js", + "safeForSimultaneousRushProcesses": true + }, + { + "name": "git-lfs-pull", + "commandKind": "global", + "summary": "pull git lfs", + "shellCommand": "node /lib/pull.js", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "description": "Fix Git LFS status", + "parameterKind": "flag", + "longName": "--fix", + "associatedCommands": ["git-lfs-check"], + "required": false + }, + { + "description": "The path array of the files", + "parameterKind": "stringList", + "longName": "--file", + "argumentName": "FILE_PATH", + "required": false, + "associatedCommands": ["git-lfs-check"] + }, + { + "description": "The version of the plugin", + "parameterKind": "flag", + "longName": "--version", + "required": false, + "associatedCommands": ["git-lfs-check"] + }, + { + "parameterKind": "string", + "description": "verbosity that can be increased", + "longName": "--verbose", + "argumentName": "VERBOSE", + "associatedCommands": ["git-lfs-check"], + "required": false + }, + { + "parameterKind": "stringList", + "argumentName": "PROJECT", + "longName": "--to", + "shortName": "-t", + "description": "choose project", + "associatedCommands": ["git-lfs-pull"] + } + ] +} diff --git a/rush-plugins/rush-git-lfs-plugin/config/heft.json b/rush-plugins/rush-git-lfs-plugin/config/heft.json new file mode 100644 index 0000000..c95b3c2 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/config/heft.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": [ + "lib" + ] + } + ], + "heftPlugins": [ + { + "plugin": "@rushstack/heft-jest-plugin" + } + ] +} \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/config/jest.config.json b/rush-plugins/rush-git-lfs-plugin/config/jest.config.json new file mode 100644 index 0000000..59202c6 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/config/jest.config.json @@ -0,0 +1,3 @@ +{ + "extends": "@rushstack/heft-jest-plugin/includes/jest-shared.config.json", +} \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/lint-staged.config.cjs b/rush-plugins/rush-git-lfs-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-git-lfs-plugin/package.json b/rush-plugins/rush-git-lfs-plugin/package.json new file mode 100644 index 0000000..c7837e3 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/package.json @@ -0,0 +1,47 @@ +{ + "name": "rush-git-lfs-plugin", + "version": "0.2.0", + "description": "Rush plugin for git-lfs", + "keywords": [ + "rush", + "plugin", + "git-lfs", + "command" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-git-lfs-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "chalk": "4.1.2", + "commander": "~9.4.0", + "execa": "~5.1.1", + "fs-extra": "~10.1.0", + "minimatch": "~5.1.1", + "ora": "5.4.1" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-jest-plugin": "~0.1.53", + "@rushstack/heft-node-rig": "1.2.31", + "@types/fs-extra": "~9.0.13", + "@types/heft-jest": "1.0.1", + "@types/minimatch": "~5.1.2", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-git-lfs-plugin/rush-plugin-manifest.json b/rush-plugins/rush-git-lfs-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..db9fdfa --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/rush-plugin-manifest.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "git-lfs-check", + "description": "Check if new files are correct managed by git-lfs", + "commandLineJsonFilePath": "command-line.json" + }, + { + "pluginName": "git-lfs-pull", + "description": "build-aware git lfs pull tooling", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-git-lfs-plugin/schema/git-lfs-option.schema.json b/rush-plugins/rush-git-lfs-plugin/schema/git-lfs-option.schema.json new file mode 100644 index 0000000..c3554a5 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/schema/git-lfs-option.schema.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Configuration for Rush Git LFS plugin", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "default": "http://json-schema.org/draft-04/schema#" + }, + "checkPattern": { + "description": "Glob patterns that need to check", + "patternProperties": { + "^.+$": { + "type": "string", + "description": "Customized size threshold for this pattern." + } + } + }, + "errorTips": { + "type": "string", + "description": "Tips that shown while there are check errors" + } + } +} \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/src/bin.ts b/rush-plugins/rush-git-lfs-plugin/src/bin.ts new file mode 100644 index 0000000..5ec3994 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/bin.ts @@ -0,0 +1,54 @@ +#!/usr/bin/env node +import { program } from 'commander'; + +import { terminal, terminalProvider, withPrefix } from './helpers/terminal'; +import { version, runCheck } from './executor'; + +export interface ICommandLineOptions { + verbose?: boolean; + fix?: boolean; + file?: string[]; + to?: string[]; +} + +const increaseVerbosity = (u: unknown, previous: number): number => { + return previous + 1; +}; +const setLogLevel = (verbose: number): void => { + if (verbose > 0) { + switch (verbose) { + case 1: + terminalProvider.verboseEnabled = true; + break; + default: + terminalProvider.verboseEnabled = true; + terminalProvider.debugEnabled = true; + break; + } + } +}; + +async function main(): Promise { + try { + await program + .version(version()) + .option('--verbose', 'Verbosity that can be increased', increaseVerbosity, 0) + .option('--fix', 'Auto fix Git LFS status') + .option('--file [file_path...]', 'The path of files') + .action(async options => { + setLogLevel(options.verbose); + await runCheck(options); + }) + .parseAsync(process.argv); + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(withPrefix(error.message)); + } else { + throw error; + } + process.exit(1); + } +} + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); diff --git a/rush-plugins/rush-git-lfs-plugin/src/constant.ts b/rush-plugins/rush-git-lfs-plugin/src/constant.ts new file mode 100644 index 0000000..d1a592d --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/constant.ts @@ -0,0 +1,9 @@ +import type { IRushGitLFSPluginOption } from './options'; +import type { NestedRequired } from './helpers/type'; + +export const DefaultOption: NestedRequired = { + checkPattern: {}, + errorTips: '', +}; + +export const PluginName: string = 'rush-git-lfs-plugin'; diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/index.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/index.ts new file mode 100644 index 0000000..dde451e --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/index.ts @@ -0,0 +1,4 @@ +export * from './version'; +export * from './run-check'; +export * from './modules'; +export * from './pull'; diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/modules/base.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/base.ts new file mode 100644 index 0000000..ae11254 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/base.ts @@ -0,0 +1,9 @@ +import type { NestedRequired } from '../../helpers/type'; +import type { IRushGitLFSPluginOption } from '../../options'; + +export interface IGitLFSModuleContext { + option: NestedRequired; +} +export abstract class GitLFSBaseModule { + abstract run(ctx: IGitLFSModuleContext): Promise; +} diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/modules/check.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/check.ts new file mode 100644 index 0000000..d5169ef --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/check.ts @@ -0,0 +1,159 @@ +/* eslint-disable @typescript-eslint/member-ordering */ +import path from 'path'; +import fse from 'fs-extra'; +import execa from 'execa'; +import { RushConfigurationProject } from '@rushstack/rush-sdk'; +import minimatch from 'minimatch'; +import ora from 'ora'; +import chalk from 'chalk'; + +import { GitLFSBaseModule, IGitLFSModuleContext } from './base'; +import { terminal, withPrefix } from '../../helpers/terminal'; +import { + toRelativePath, + toAbsolutePath, + RushRootFolder, + findFileBelongProject, +} from '../../helpers/file-path-analyser'; + +export interface IGitLFSCheckModuleContext extends IGitLFSModuleContext { + files: string[]; + result: IGitLFSCheckModuleFileError[]; + fix?: boolean; + spinner: ora.Ora; +} + +export interface IGitLFSCheckModuleFileError { + file: string; + errorType?: GitLFSCheckModuleErrorType; + fixed?: boolean; +} + +export const enum GitLFSCheckModuleErrorType { + FileNeedToBeTrackedByLFS, + FixFileLFSStatusFail, + GitAddFail, +} + +export class GitLFSCheckModule extends GitLFSBaseModule { + public isFileNeedToTrack(p: string, pattern: Record): boolean { + const entries: [string, number][] = Object.entries(pattern); + + for (const [ptn, size] of entries) { + if (minimatch(toRelativePath(p), ptn)) { + const stat: fse.Stats = fse.statSync(toAbsolutePath(p)); + return stat.size > size; + } + } + return false; + } + + public isTrackedByLFS = (p: string): boolean => { + /* use git check-attr to test if a file was managed by git-lfs */ + try { + const { exitCode, stdout } = execa.commandSync( + `git check-attr --all -- ${toRelativePath(p)}`, + { + cwd: RushRootFolder, + } + ); + return exitCode === 0 && stdout.includes('filter: lfs'); + } catch (e) { + return false; + } + }; + + public fixFile = (p: string): void => { + terminal.writeVerboseLine(withPrefix(`Try adding ${toRelativePath(p)} to Git LFS`)); + const project: RushConfigurationProject | undefined = findFileBelongProject(p); + /* if we can't find a project the file belong to, just run git lfs track at root */ + const runCWD: string = typeof project === 'undefined' ? RushRootFolder : project.projectFolder; + const relativePath: string = path.relative(runCWD, toRelativePath(p)); + const { exitCode } = execa.commandSync(`git lfs track ${relativePath}`, { + cwd: toAbsolutePath(runCWD), + }); + if (exitCode !== 0) { + throw GitLFSCheckModuleErrorType.FixFileLFSStatusFail; + } + this.addFileToGit(path.resolve(runCWD, '.gitattributes')); + if (exitCode !== 0) { + throw GitLFSCheckModuleErrorType.GitAddFail; + } + }; + + public addFileToGit = (p: string): void => { + terminal.writeVerboseLine(withPrefix(`Trying git add on ${toRelativePath(p)}`)); + const { exitCode } = execa.commandSync(`git add ${toRelativePath(p)}`, { + cwd: toAbsolutePath(RushRootFolder), + }); + if (exitCode !== 0) { + throw GitLFSCheckModuleErrorType.GitAddFail; + } + }; + + public run = async (ctx: IGitLFSCheckModuleContext): Promise => { + const { + files, + result, + fix, + option: { checkPattern }, + spinner, + } = ctx; + + spinner.start('Start Git LFS check...'); + for (const f of files) { + terminal.writeVerboseLine(withPrefix(`Checking file status for ${toRelativePath(f)}`)); + spinner.text = `Checking file status for ${toRelativePath(f)}`; + const isNeedToTrack: boolean = this.isFileNeedToTrack(f, checkPattern); + + if (isNeedToTrack && !this.isTrackedByLFS(f)) { + let isFixed: boolean = false; + + if (fix) { + try { + terminal.writeVerboseLine(withPrefix(`Trying to fix ${toRelativePath(f)}`)); + this.fixFile(f); + isFixed = true; + terminal.writeVerboseLine(withPrefix(`Fixed ${toRelativePath(f)}`)); + } catch (e) { + terminal.writeVerboseLine( + withPrefix(`Error occurs while fixing ${toRelativePath(f)} ${e}`) + ); + } + } + if (isFixed) { + spinner.warn( + `Git LFS check failed for ${chalk.red( + toRelativePath(f) + )}, but was automatically fixed` + ); + } else { + result.push({ + file: toRelativePath(f), + errorType: GitLFSCheckModuleErrorType.FileNeedToBeTrackedByLFS, + }); + spinner.fail( + `Git LFS check failed for ${chalk.red(toRelativePath(f))}${ + fix ? " and can't be automatically fixed" : '' + }` + ); + } + } else { + result.push({ + file: toRelativePath(f), + }); + } + } + + const errors: IGitLFSCheckModuleFileError[] = result.filter( + e => typeof e.errorType !== 'undefined' + ); + if (errors.length > 0) { + spinner.fail('Git LFS check failed'); + } else { + spinner.succeed('Git LFS check success'); + } + + return result; + }; +} diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/modules/index.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/index.ts new file mode 100644 index 0000000..01a8e34 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/modules/index.ts @@ -0,0 +1 @@ +export * from './check'; diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/pull.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/pull.ts new file mode 100644 index 0000000..ce48e30 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/pull.ts @@ -0,0 +1,65 @@ +import { Executable } from '@rushstack/node-core-library'; +import { SpawnSyncReturns } from 'child_process'; + +interface IProject { + path: string; +} + +// get all related packages include project in workspace by projectName +const getPackagesByProjectName = ( + projectNames: Array +): { + projects: Array; +} => { + const projectParams: Array> = projectNames.map((projectName) => ['-t', projectName]); + const result: SpawnSyncReturns = Executable.spawnSync( + 'rush', + ['list'].concat(...projectParams, '--json') + ); + if (result.status === 0) { + return JSON.parse(result.stdout); + } + throw new Error(`rush list error code ${result.status}`); +}; + +const getAllIncludedPaths = ( + projects: Array<{ + path: string; + }> +): string => projects.map((p) => p.path).join(','); + +// default action +const gitLfsPull = (): void => { + Executable.spawnSync('git', ['lfs', 'pull']); +}; +const gitLfsInstall = (): void => { + Executable.spawnSync('git', ['lfs', 'install']); +}; +/** + * + * @param {*} to stringList, projectName(s) + */ +const gitLfsPullByProject = (projectNames: Array): void => { + const { + projects + }: { + projects: Array; + } = getPackagesByProjectName(projectNames); + // git lfs pull --include paths + const includePaths: string = getAllIncludedPaths(projects); + if (projects.length > 0) { + const result: SpawnSyncReturns = Executable.spawnSync('git', [ + 'lfs', + 'pull', + '--include', + includePaths + ]); + if (result.status !== 0) { + throw new Error(`git lfs pull --include failed ${result.status}`); + } + } else { + throw new Error('no projects'); + } +}; + +export { gitLfsPull, gitLfsInstall, gitLfsPullByProject }; diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/run-check.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/run-check.ts new file mode 100644 index 0000000..3e15970 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/run-check.ts @@ -0,0 +1,53 @@ +import { GitLFSCheckModule, IGitLFSCheckModuleContext } from './modules'; + +import { IRushGitLFSPluginOption, loadPluginOptions } from '../options'; + +import { getFilePathsFromChangedFiles, validateFilePaths } from '../helpers/file-path-analyser'; +import { terminal, withPrefix } from '../helpers/terminal'; + +import type { NestedRequired } from '../helpers/type'; +import type { ICommandLineOptions } from '../bin'; +import ora from 'ora'; + +const normalizeCheckContext = ( + commandLineOption: ICommandLineOptions +): IGitLFSCheckModuleContext => { + // eslint-disable-next-line prefer-const + let { file: files, fix } = commandLineOption; + if (typeof files === 'undefined') { + files = getFilePathsFromChangedFiles(); + } else { + try { + validateFilePaths(files); + } catch (e: any) { + if (e.message) { + terminal.writeErrorLine(withPrefix(e.message)); + } else { + throw e; + } + process.exit(1); + } + } + + const option: NestedRequired = loadPluginOptions(); + const spinner: ora.Ora = ora(); + return { + result: [], + fix, + files, + option, + spinner, + }; +}; + +export const runCheck = async (commandLineOption: ICommandLineOptions): Promise => { + const checker: GitLFSCheckModule = new GitLFSCheckModule(); + const ctx: IGitLFSCheckModuleContext = normalizeCheckContext(commandLineOption); + await checker.run(ctx); + if (ctx.result.filter(e => typeof e.errorType !== 'undefined' && !e.fixed).length > 0) { + if (ctx.option.errorTips) { + terminal.writeLine(ctx.option.errorTips); + } + process.exit(1); + } +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/executor/version.ts b/rush-plugins/rush-git-lfs-plugin/src/executor/version.ts new file mode 100644 index 0000000..57594c3 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/executor/version.ts @@ -0,0 +1,8 @@ +import path from 'path'; +import fse from 'fs-extra'; + +export const version = (): string => { + // eslint-disable-next-line @typescript-eslint/typedef + const pkg = fse.readJSONSync(path.resolve(__dirname, '../../package.json')); + return pkg.version; +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/helpers/file-path-analyser.ts b/rush-plugins/rush-git-lfs-plugin/src/helpers/file-path-analyser.ts new file mode 100644 index 0000000..3007034 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/helpers/file-path-analyser.ts @@ -0,0 +1,75 @@ +import path from 'path'; +import execa from 'execa'; +import fse from 'fs-extra'; +import { RushConfiguration, RushConfigurationProject } from '@rushstack/rush-sdk'; + +import { withPrefix, terminal } from './terminal'; + +export const RushConfig: RushConfiguration = RushConfiguration.loadFromDefaultLocation(); + +export const RushRootFolder: string = RushConfig.rushJsonFolder; + +export const RushCWD: string = process.env.RUSH_INVOKED_FOLDER!; + +export const toAbsolutePath = (p: string): string => { + return path.resolve(RushCWD, p); +}; +export const toRelativePath = (p: string): string => { + return path.relative(RushRootFolder, toAbsolutePath(p)); +}; + +const enum ErrorMsg { + GetChangedFileError = 'Error occurs when get changed files by running "git diff --cached --name-only --diff-filter=ACMR", please check your git environment.', + FilePathNotCorrect = 'The input files pattern is not correct, please make sure you set the correct file paths.', + FilePathNotExist = 'File path not exist, please check your input file.', +} + +export const getFilePathsFromChangedFiles = (): string[] => { + /* use git diff to get changed files */ + terminal.writeVerboseLine(withPrefix('Using git diff to get changed files.')); + let files: string[]; + try { + const { exitCode, stdout, stderr } = execa.commandSync( + 'git diff --name-only --diff-filter=ACMR --cached' + ); + if (exitCode === 0) { + files = stdout + .split(/\r?\n|\r|\n/g) + .filter(s => s.length) + .map(p => path.resolve(RushRootFolder, p)); + terminal.writeVerboseLine(withPrefix(`Changed files paths\n${files.join(',\n')}`)); + return files; + } else { + terminal.writeErrorLine(withPrefix(stderr)); + throw new Error(ErrorMsg.GetChangedFileError); + } + } catch (e: any) { + terminal.writeErrorLine(withPrefix(e)); + throw new Error(ErrorMsg.GetChangedFileError); + } +}; + +export const validateFilePaths = (files: string[]): void => { + if (!files.every(f => typeof f === 'string')) { + /* check if every item in array is string */ + throw new Error(ErrorMsg.FilePathNotCorrect); + } + + if (!files.every(f => fse.existsSync(toAbsolutePath(f)))) { + /* check if every file was exist */ + throw new Error(ErrorMsg.FilePathNotExist); + } +}; + +export const findFileBelongProject = (f: string): RushConfigurationProject | undefined => { + const projects: RushConfigurationProject[] = RushConfig.projects; + + const relativePath: string = toRelativePath(f); + + for (const p of projects) { + const pFolder: string = path.relative(RushRootFolder, p.projectFolder); + if (relativePath.startsWith(pFolder)) { + return p; + } + } +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/helpers/terminal.ts b/rush-plugins/rush-git-lfs-plugin/src/helpers/terminal.ts new file mode 100644 index 0000000..ddf6a87 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/helpers/terminal.ts @@ -0,0 +1,13 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from '@rushstack/node-core-library'; + +import { PluginName } from '../constant'; + +export const terminalProvider: ConsoleTerminalProvider = new ConsoleTerminalProvider(); +export const terminal: Terminal = new Terminal(terminalProvider); + +export const withPrefix = (msg: string): string => { + return `[${PluginName}]` + msg; +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/helpers/type.ts b/rush-plugins/rush-git-lfs-plugin/src/helpers/type.ts new file mode 100644 index 0000000..f40929f --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/helpers/type.ts @@ -0,0 +1,6 @@ +export type NestedRequired = { + [P in keyof T]-?: NestedRequired; +}; +export type NestedPartial = { + [P in keyof T]?: NestedPartial; +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/index.ts b/rush-plugins/rush-git-lfs-plugin/src/index.ts new file mode 100644 index 0000000..49e4fd4 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/index.ts @@ -0,0 +1,2 @@ +export * from './constant'; +export * from './options'; \ No newline at end of file diff --git a/rush-plugins/rush-git-lfs-plugin/src/options.ts b/rush-plugins/rush-git-lfs-plugin/src/options.ts new file mode 100644 index 0000000..67c5cd8 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/options.ts @@ -0,0 +1,35 @@ +import path from 'path'; +import { RushConfiguration } from '@rushstack/rush-sdk'; + +import fse from 'fs-extra'; + +import { PluginName, DefaultOption } from './constant'; +import { NestedRequired } from './helpers/type'; + +export interface IRushGitLFSPluginOption { + checkPattern: Record; + errorTips?: string; +} + +export const loadPluginOptions = (): NestedRequired => { + const rushConfig: RushConfiguration = RushConfiguration.loadFromDefaultLocation(); + const pluginConfigFolder: string = rushConfig.rushPluginOptionsFolder; + const optionFilePath: string = path.resolve(pluginConfigFolder, `${PluginName}.json`); + + const option: NestedRequired = DefaultOption; + + if (fse.existsSync(optionFilePath)) { + const customOption: Partial = fse.readJSONSync(optionFilePath); + + if (typeof customOption.checkPattern === 'object') { + option.checkPattern = { + ...option.checkPattern, + ...customOption.checkPattern, + }; + } + if (customOption.errorTips) { + option.errorTips = customOption.errorTips; + } + } + return option; +}; diff --git a/rush-plugins/rush-git-lfs-plugin/src/pull.ts b/rush-plugins/rush-git-lfs-plugin/src/pull.ts new file mode 100644 index 0000000..27de9be --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/pull.ts @@ -0,0 +1,32 @@ +/** + * git lfs pull related project files + * rush git-lsf-pull -t/--to projectName + */ +import { program } from 'commander'; +import { gitLfsInstall, gitLfsPullByProject } from './executor'; +import { terminal } from './helpers/terminal'; + +(async () => { + program.option('--to ', '-t ', 'select project').action(async (params) => { + const { to } = params; + gitLfsInstall(); + try { + gitLfsPullByProject([].concat(to)); + terminal.writeLine(`git-lfs-pull pull ${to} success`); + } catch (error: any) { + if (error && error.toString) { + terminal.writeErrorLine(error.toString()); + } else { + throw error; + } + process.exit(1); + } + }); + + program.on('command:*', () => { + console.error('undefined command', program.args.join(' ')); + process.exit(1); + }); + + await program.parseAsync(process.argv); +})().catch((e: any) => console.error(e && e.message ? e.message : e)); diff --git a/rush-plugins/rush-git-lfs-plugin/src/tests/executor/core.test.ts b/rush-plugins/rush-git-lfs-plugin/src/tests/executor/core.test.ts new file mode 100644 index 0000000..ac2fa19 --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/tests/executor/core.test.ts @@ -0,0 +1,78 @@ +import { GitLFSCheckModule } from '../../executor/modules/check'; +import FileFactory from '../setup/TestFileFactory'; + +describe('lfs file detect', () => { + it('should detect binary image file correctly', () => { + const factory = FileFactory.getInstance(); + const bFile = factory.createBinaryFile('test-b'); + const tFile = factory.createTextFile('test-t'); + const checker = new GitLFSCheckModule(); + expect(checker.isFileNeedToTrack(bFile, { '**/*.png': 0, '**/*': 5 * 1024 * 1024 })).toBe(true); + expect(checker.isFileNeedToTrack(tFile, { '**/*.png': 0, '**/*': 5 * 1024 * 1024 })).toBe( + false + ); + }); + + it('should detect large file correctly', () => { + const factory = FileFactory.getInstance(); + + const smallFile = factory.createSizedFile('sFile', 4 * 1024); + const largeFile = factory.createSizedFile('lFile', 6 * 1024 * 1024); + const checker = new GitLFSCheckModule(); + + expect(checker.isFileNeedToTrack(smallFile, { '**/*': 5 * 1024 * 1024 })).toBe(false); + expect(checker.isFileNeedToTrack(largeFile, { '**/*': 5 * 1024 * 1024 })).toBe(true); + }); + + it('should detect large file with customized files threshold correctly', () => { + const factory = FileFactory.getInstance(); + + const tsFile = factory.createSizedFile('tsFile.ts', 6 * 1024 * 1024); + const jsFile = factory.createSizedFile('jsFile.js', 2 * 1024 * 1024); + const checker = new GitLFSCheckModule(); + + expect(checker.isFileNeedToTrack(tsFile, { '**/*.ts': 7 * 1024 * 1024 })).toBe(false); + expect(checker.isFileNeedToTrack(jsFile, { '**/*.js': 1 * 1024 * 1024 })).toBe(true); + }); + + it('should detect LFS status correctly', () => { + const factory = FileFactory.getInstance(); + + const lfsFile = factory.createBinaryFile('lfsFile'); + const checker = new GitLFSCheckModule(); + + factory.addFileToLFS(lfsFile); + + expect(checker.isTrackedByLFS(lfsFile)).toBe(true); + + factory.removeFileFromLFS(lfsFile); + expect(checker.isTrackedByLFS(lfsFile)).toBe(false); + }); + + it('should add file to git correctly', () => { + const factory = FileFactory.getInstance(); + const checker = new GitLFSCheckModule(); + + const tempFile = factory.createTextFile('tempFile'); + + expect(() => checker.addFileToGit(tempFile)).toThrow(); + }); + + afterAll(() => { + FileFactory.getInstance().cleanTempFolder(); + }); +}); + +// describe('file parameters', () => { +// it('should get changed files when file parameters are not array', () => { +// const checker = new GitLFSCheckModule(); +// // @ts-ignore +// const files = checker._normalizeFilePaths(1 as any); +// expect(Array.isArray(files)).toBe(true); +// }); +// it('should throw error when file parameters are not correct', () => { +// const checker = new GitLFSCheckModule(); +// // @ts-ignore +// expect(() => checker._normalizeFilePaths([1, 2] as any[])).toThrowError(); +// }); +// }); diff --git a/rush-plugins/rush-git-lfs-plugin/src/tests/executor/verison.test.ts b/rush-plugins/rush-git-lfs-plugin/src/tests/executor/verison.test.ts new file mode 100644 index 0000000..4b5683a --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/tests/executor/verison.test.ts @@ -0,0 +1,15 @@ +import path from 'path'; +import fs from 'fs'; + +import { version } from '../../executor/version'; + +describe('version parameter', () => { + it('version should match current version in package.json', () => { + const pkg = JSON.parse( + fs + .readFileSync(path.resolve(__dirname, '../../../package.json'), { encoding: 'utf-8' }) + .toString() + ); + expect(version()).toStrictEqual(pkg.version); + }); +}); diff --git a/rush-plugins/rush-git-lfs-plugin/src/tests/helpers/file-path-analyser.test.ts b/rush-plugins/rush-git-lfs-plugin/src/tests/helpers/file-path-analyser.test.ts new file mode 100644 index 0000000..f5ad12f --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/tests/helpers/file-path-analyser.test.ts @@ -0,0 +1,64 @@ +jest.mock('execa'); +import execa from 'execa'; +import path from 'path'; + +import { + getFilePathsFromChangedFiles, + findFileBelongProject, + validateFilePaths, +} from '../../helpers/file-path-analyser'; +import { terminal, terminalProvider } from '../../helpers/terminal'; + +const mockCommandSyncReturn = (result: Partial): void => { + ( + execa.commandSync as unknown as jest.MockedFunction + ).mockImplementation((() => { + return result; + }) as any); +}; + +describe('test file path analyser', () => { + it('should get changed files by git diff', () => { + const testPath = path.resolve(__dirname); + mockCommandSyncReturn({ + exitCode: 0, + stdout: testPath, + }); + expect(getFilePathsFromChangedFiles()?.[0]).toStrictEqual(testPath); + }); + + it('should throw error if git diff run failed', () => { + mockCommandSyncReturn({ exitCode: 1, stderr: 'This should be an error' }); + terminal.unregisterProvider(terminalProvider); + expect(getFilePathsFromChangedFiles).toThrowError(); + terminal.registerProvider(terminalProvider); + }); + + it('should find file path belong package correctly', () => { + const p1 = path.resolve(__dirname); + + const p2 = path.resolve(__dirname, '../../../../../rush.json'); + const p3 = path.resolve('/some/path/that/incorrect'); + expect(findFileBelongProject(p1)?.packageName).toStrictEqual('rush-git-lfs-plugin'); + expect(findFileBelongProject(p2)).toBeUndefined(); + expect(findFileBelongProject(p3)).toBeUndefined(); + }); + + it('should valid path correctly', () => { + const pathsCorrect = [ + path.resolve(__dirname), + path.resolve(__dirname, '../../../package.json'), + ]; + + const pathsPatternIncorrect = [path.resolve(__dirname), 20, Boolean]; + + const pathsFileNotExist = [ + path.resolve(__dirname), + path.resolve(__dirname, './not-exist-file.ts'), + ]; + + expect(() => validateFilePaths(pathsCorrect)).not.toThrow(); + expect(() => validateFilePaths(pathsPatternIncorrect as string[])).toThrowError(); + expect(() => validateFilePaths(pathsFileNotExist)).toThrowError(); + }); +}); diff --git a/rush-plugins/rush-git-lfs-plugin/src/tests/setup/TestFileFactory.ts b/rush-plugins/rush-git-lfs-plugin/src/tests/setup/TestFileFactory.ts new file mode 100644 index 0000000..97a9f0e --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/src/tests/setup/TestFileFactory.ts @@ -0,0 +1,63 @@ +import path from 'path'; +import fse from 'fs-extra'; +import execa from 'execa'; + +export default class TestFileFactory { + private static _instance?: TestFileFactory; + public tempFolder: string = path.resolve(__dirname, '../temp'); + public static getInstance(): TestFileFactory { + if (!this._instance) { + this._instance = new TestFileFactory(); + } + return this._instance; + } + + private _writeFile(fileName: string, data: any): string { + const filePath: string = path.resolve(this.tempFolder, `${fileName}`); + fse.ensureDirSync(path.dirname(filePath)); + fse.writeFileSync(filePath, data); + return filePath; + } + + public createTextFile(fileName: string): string { + const str: string = (Math.random() + 1).toString(36).substring(7); + + return this._writeFile(fileName, str); + } + public createBinaryFile(fileName: string): string { + const simplePngBase64Str: string = + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAKElEQVQ4jWNgYGD4Twzu6FhFFGYYNXDUwGFpIAk2E4dHDRw1cDgaCAASFOffhEIO3gAAAABJRU5ErkJggg=='; + + return this._writeFile(fileName + '.png', Buffer.from(simplePngBase64Str, 'base64')); + } + public createSizedFile(fileName: string, size: number): string { + const filePath: string = path.resolve(this.tempFolder, fileName); + fse.ensureFileSync(filePath); + const f: number = fse.openSync(filePath, 'w'); + fse.writeSync(f, 'ok', Math.max(0, size - 2)); + fse.closeSync(f); + return filePath; + } + public addFileToLFS(filePath: string): void { + const relativePath: string = path.relative(this.tempFolder, filePath); + const { exitCode } = execa.commandSync(`git lfs track ${relativePath}`, { + cwd: this.tempFolder, + }); + if (exitCode !== 0) { + throw new Error('Add file to lfs failed'); + } + } + public removeFileFromLFS(filePath: string): void { + const relativePath: string = path.relative(this.tempFolder, filePath); + const { exitCode } = execa.commandSync(`git lfs untrack ${relativePath}`, { + cwd: this.tempFolder, + }); + if (exitCode !== 0) { + throw new Error('Remove file from lfs failed'); + } + } + + public cleanTempFolder(): void { + fse.removeSync(this.tempFolder); + } +} diff --git a/rush-plugins/rush-git-lfs-plugin/tsconfig.json b/rush-plugins/rush-git-lfs-plugin/tsconfig.json new file mode 100644 index 0000000..65e6f4c --- /dev/null +++ b/rush-plugins/rush-git-lfs-plugin/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node", + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/.eslintrc.js b/rush-plugins/rush-init-project-plugin/.eslintrc.js new file mode 100644 index 0000000..f3928da --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/.eslintrc.js @@ -0,0 +1,15 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@rushstack/no-new-null": "off", + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-init-project-plugin/.gitignore b/rush-plugins/rush-init-project-plugin/.gitignore new file mode 100644 index 0000000..e6a4c36 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/.gitignore @@ -0,0 +1,3 @@ +lib/ +temp/ +output/ \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/.npmignore b/rush-plugins/rush-init-project-plugin/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-init-project-plugin/CHANGELOG.json b/rush-plugins/rush-init-project-plugin/CHANGELOG.json new file mode 100644 index 0000000..e0ca007 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/CHANGELOG.json @@ -0,0 +1,316 @@ +{ + "name": "rush-init-project-plugin", + "entries": [ + { + "version": "0.9.0", + "tag": "rush-init-project-plugin_v0.9.0", + "date": "Mon, 20 Mar 2023 07:15:13 GMT", + "comments": { + "minor": [ + { + "comment": "add global plugin" + } + ] + } + }, + { + "version": "0.8.2", + "tag": "rush-init-project-plugin_v0.8.2", + "date": "Thu, 16 Mar 2023 12:08:26 GMT", + "comments": { + "patch": [ + { + "comment": "fix in -a mode answers are not complete" + } + ] + } + }, + { + "version": "0.8.1", + "tag": "rush-init-project-plugin_v0.8.1", + "date": "Thu, 16 Mar 2023 08:30:30 GMT", + "comments": { + "patch": [ + { + "comment": "remove duplicate loadTemplateConfiguration" + } + ] + } + }, + { + "version": "0.8.0", + "tag": "rush-init-project-plugin_v0.8.0", + "date": "Mon, 13 Mar 2023 09:45:27 GMT", + "comments": { + "minor": [ + { + "comment": "add template schema to manage templates and add assign unscopedPackageName after inquery" + } + ] + } + }, + { + "version": "0.7.2", + "tag": "rush-init-project-plugin_v0.7.2", + "date": "Tue, 28 Feb 2023 08:06:50 GMT", + "comments": { + "patch": [ + { + "comment": "remove filter prompts in rush init-project" + } + ] + } + }, + { + "version": "0.7.1", + "tag": "rush-init-project-plugin_v0.7.1", + "date": "Thu, 02 Feb 2023 11:25:18 GMT", + "comments": { + "patch": [ + { + "comment": "fix ui comfirm" + } + ] + } + }, + { + "version": "0.7.0", + "tag": "rush-init-project-plugin_v0.7.0", + "date": "Wed, 01 Feb 2023 09:06:22 GMT", + "comments": { + "minor": [ + { + "comment": "add ui option in cli" + } + ] + } + }, + { + "version": "0.6.1", + "tag": "rush-init-project-plugin_v0.6.1", + "date": "Wed, 07 Dec 2022 09:05:36 GMT", + "comments": { + "patch": [ + { + "comment": "fix getGitUserName logic" + } + ] + } + }, + { + "version": "0.6.0", + "tag": "rush-init-project-plugin_v0.6.0", + "date": "Mon, 05 Dec 2022 13:00:38 GMT", + "comments": { + "minor": [ + { + "comment": "Add done hook" + } + ] + } + }, + { + "version": "0.5.0", + "tag": "rush-init-project-plugin_v0.5.0", + "date": "Mon, 28 Nov 2022 03:27:55 GMT", + "comments": { + "minor": [ + { + "comment": "Support displayName to IConfig in init config file for rush-init-project-plugin" + } + ] + } + }, + { + "version": "0.4.0", + "tag": "rush-init-project-plugin_v0.4.0", + "date": "Wed, 23 Nov 2022 06:29:45 GMT", + "comments": { + "minor": [ + { + "comment": "set git config user.name as default authorName" + } + ] + } + }, + { + "version": "0.3.1", + "tag": "rush-init-project-plugin_v0.3.1", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + }, + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.3.0", + "tag": "rush-init-project-plugin_v0.3.0", + "date": "Tue, 30 Aug 2022 17:47:59 GMT", + "comments": { + "none": [ + { + "comment": "Add tests" + } + ], + "minor": [ + { + "comment": "Adds \"decoupledLocalDependencies\" and \"tags\" to the fields of the default rush project configuration" + }, + { + "comment": "Add CLI parameters -a, --answer to accept answers from external JSON" + } + ] + } + }, + { + "version": "0.2.2", + "tag": "rush-init-project-plugin_v0.2.2", + "date": "Tue, 22 Mar 2022 03:26:29 GMT", + "comments": { + "patch": [ + { + "comment": "upgrade sort-package-json version" + } + ] + } + }, + { + "version": "0.2.1", + "tag": "rush-init-project-plugin_v0.2.1", + "date": "Thu, 24 Feb 2022 11:57:31 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade rush-sdk to load rushConfiguration" + } + ] + } + }, + { + "version": "0.2.0", + "tag": "rush-init-project-plugin_v0.2.0", + "date": "Wed, 09 Feb 2022 11:08:02 GMT", + "comments": { + "minor": [ + { + "comment": "Add defaultProjectConfiguration & related hook in template configuration" + } + ] + } + }, + { + "version": "0.1.4", + "tag": "rush-init-project-plugin_v0.1.4", + "date": "Tue, 18 Jan 2022 17:04:14 GMT", + "comments": { + "patch": [ + { + "comment": "Dot files in template should be added now" + } + ] + } + }, + { + "version": "0.1.3", + "tag": "rush-init-project-plugin_v0.1.3", + "date": "Tue, 18 Jan 2022 16:54:18 GMT", + "comments": { + "patch": [ + { + "comment": "Fix add 0 template files in Windows" + } + ] + } + }, + { + "version": "0.1.2", + "tag": "rush-init-project-plugin_v0.1.2", + "date": "Mon, 27 Dec 2021 12:51:25 GMT", + "comments": { + "patch": [ + { + "comment": "Fix template file glob options" + } + ] + } + }, + { + "version": "0.1.1", + "tag": "rush-init-project-plugin_v0.1.1", + "date": "Mon, 27 Dec 2021 08:30:37 GMT", + "comments": { + "patch": [ + { + "comment": "Add a workaround for rushVersion validaty" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-init-project-plugin_v0.1.0", + "date": "Sun, 26 Dec 2021 11:48:25 GMT", + "comments": { + "minor": [ + { + "comment": "Add configuration and plugin system" + } + ] + } + }, + { + "version": "0.0.5", + "tag": "rush-init-project-plugin_v0.0.5", + "date": "Fri, 24 Dec 2021 15:37:38 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.0.4", + "tag": "rush-init-project-plugin_v0.0.4", + "date": "Fri, 24 Dec 2021 15:31:53 GMT", + "comments": { + "patch": [ + { + "comment": "Update package.json" + } + ] + } + }, + { + "version": "0.0.3", + "tag": "rush-init-project-plugin_v0.0.3", + "date": "Fri, 24 Dec 2021 15:25:33 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.0.2", + "tag": "rush-init-project-plugin_v0.0.2", + "date": "Fri, 24 Dec 2021 14:54:41 GMT", + "comments": { + "patch": [ + { + "comment": "first impl" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-init-project-plugin/CHANGELOG.md b/rush-plugins/rush-init-project-plugin/CHANGELOG.md new file mode 100644 index 0000000..5efb978 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/CHANGELOG.md @@ -0,0 +1,181 @@ +# Change Log - rush-init-project-plugin + +This log was last generated on Mon, 20 Mar 2023 07:15:13 GMT and should not be manually modified. + +## 0.9.0 +Mon, 20 Mar 2023 07:15:13 GMT + +### Minor changes + +- add global plugin + +## 0.8.2 +Thu, 16 Mar 2023 12:08:26 GMT + +### Patches + +- fix in -a mode answers are not complete + +## 0.8.1 +Thu, 16 Mar 2023 08:30:30 GMT + +### Patches + +- remove duplicate loadTemplateConfiguration + +## 0.8.0 +Mon, 13 Mar 2023 09:45:27 GMT + +### Minor changes + +- add template schema to manage templates and add assign unscopedPackageName after inquery + +## 0.7.2 +Tue, 28 Feb 2023 08:06:50 GMT + +### Patches + +- remove filter prompts in rush init-project + +## 0.7.1 +Thu, 02 Feb 2023 11:25:18 GMT + +### Patches + +- fix ui comfirm + +## 0.7.0 +Wed, 01 Feb 2023 09:06:22 GMT + +### Minor changes + +- add ui option in cli + +## 0.6.1 +Wed, 07 Dec 2022 09:05:36 GMT + +### Patches + +- fix getGitUserName logic + +## 0.6.0 +Mon, 05 Dec 2022 13:00:38 GMT + +### Minor changes + +- Add done hook + +## 0.5.0 +Mon, 28 Nov 2022 03:27:55 GMT + +### Minor changes + +- Support displayName to IConfig in init config file for rush-init-project-plugin + +## 0.4.0 +Wed, 23 Nov 2022 06:29:45 GMT + +### Minor changes + +- set git config user.name as default authorName + +## 0.3.1 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme +- Update readme + +## 0.3.0 +Tue, 30 Aug 2022 17:47:59 GMT + +### Minor changes + +- Adds "decoupledLocalDependencies" and "tags" to the fields of the default rush project configuration +- Add CLI parameters -a, --answer to accept answers from external JSON + +## 0.2.2 +Tue, 22 Mar 2022 03:26:29 GMT + +### Patches + +- upgrade sort-package-json version + +## 0.2.1 +Thu, 24 Feb 2022 11:57:31 GMT + +### Patches + +- Upgrade rush-sdk to load rushConfiguration + +## 0.2.0 +Wed, 09 Feb 2022 11:08:02 GMT + +### Minor changes + +- Add defaultProjectConfiguration & related hook in template configuration + +## 0.1.4 +Tue, 18 Jan 2022 17:04:14 GMT + +### Patches + +- Dot files in template should be added now + +## 0.1.3 +Tue, 18 Jan 2022 16:54:18 GMT + +### Patches + +- Fix add 0 template files in Windows + +## 0.1.2 +Mon, 27 Dec 2021 12:51:25 GMT + +### Patches + +- Fix template file glob options + +## 0.1.1 +Mon, 27 Dec 2021 08:30:37 GMT + +### Patches + +- Add a workaround for rushVersion validaty + +## 0.1.0 +Sun, 26 Dec 2021 11:48:25 GMT + +### Minor changes + +- Add configuration and plugin system + +## 0.0.5 +Fri, 24 Dec 2021 15:37:38 GMT + +### Patches + +- Update readme + +## 0.0.4 +Fri, 24 Dec 2021 15:31:53 GMT + +### Patches + +- Update package.json + +## 0.0.3 +Fri, 24 Dec 2021 15:25:33 GMT + +### Patches + +- Update readme + +## 0.0.2 +Fri, 24 Dec 2021 14:54:41 GMT + +### Patches + +- first impl + diff --git a/rush-plugins/rush-init-project-plugin/LICENSE b/rush-plugins/rush-init-project-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-init-project-plugin/README.md b/rush-plugins/rush-init-project-plugin/README.md new file mode 100644 index 0000000..833f5d2 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/README.md @@ -0,0 +1,55 @@ +# rush-init-project-plugin + +Initialize project in Rush.js monorepo like a pro! + +# Prerequisite + +Rush.js >= 5.57.0 + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Adding your first template + +Let's say you want to add a new template named `my-template`, put the template files under `common/_templates/my-template` folder. + +``` +common/_templates +└── my-template + ├── README.md + └── package.json +``` + +Now, run `rush init-project` prompts you select a template list, which contains `my-template`. + +After you answer some simple questions, files under `common/_templates/my-template` will be added into your project folder, and project configuration will be added to `rush.json` as well. + +# Advance Usage + +Kind of boring in a template way? + +You can create a configuration file to extend initialization process. + +See [HERE](./docs/init_project_configuration.md) for detail. + +# Tech Notes + +The whole CLI is based on [node-plop](https://www.npmjs.com/package/plop) + +All directories under `common/_templates/` are template source code, except those who prefixes with `_`. For instance, folder named `_plugins` is treated as internal folder not template folder where you can store shared code across templates. + +All source code will be rendered by [handlebars](https://handlebarsjs.com/guide/), while using custom render engine is supported. + +Plenty of handlebar helpers are provided as default by [handlebars-helpers](https://www.npmjs.com/package/handlebars-helpers) + +Third party node modules can be used in `init.config` configuration file by installing them into the corresponding autoinstaller folder, such as `common/autoinstallers/rush-plugins/`. + +Default prompts includes: +- `packageName`: `"name"` field in `package.json` +- `unscopedPackageName`: `packageName` without npm scope +- `projectFolder`: the dest file path where the template will be rendered +- `description`: project description +- `authorName`: author name diff --git a/rush-plugins/rush-init-project-plugin/command-line.json b/rush-plugins/rush-init-project-plugin/command-line.json new file mode 100644 index 0000000..cea7475 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/command-line.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "init-project", + "commandKind": "global", + "summary": "Initialize project in this monorepo", + "shellCommand": "rush-init-project", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "description": "Provide predefined answers with JSON string", + "shortName": "-a", + "longName": "--answer", + "argumentName": "ANSWER", + "associatedCommands": ["init-project"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Provide the option isDryRun in plugin context", + "shortName": "-d", + "longName": "--dry-run", + "associatedCommands": ["init-project"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Provide verbose log output", + "shortName": "-v", + "longName": "--verbose", + "associatedCommands": ["init-project"], + "required": false + }, + { + "parameterKind": "flag", + "description": "Provide terminal ui operation", + "longName": "--ui", + "associatedCommands": ["init-project"], + "required": false + } + ] +} diff --git a/rush-plugins/rush-init-project-plugin/config/heft.json b/rush-plugins/rush-init-project-plugin/config/heft.json new file mode 100644 index 0000000..2a2bf49 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/config/heft.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ], + + "heftPlugins": [ + { "plugin": "@rushstack/heft-jest-plugin" } + ] +} diff --git a/rush-plugins/rush-init-project-plugin/config/jest.config.json b/rush-plugins/rush-init-project-plugin/config/jest.config.json new file mode 100644 index 0000000..b6f305e --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/config/jest.config.json @@ -0,0 +1,3 @@ +{ + "extends": "@rushstack/heft-jest-plugin/includes/jest-shared.config.json" +} diff --git a/rush-plugins/rush-init-project-plugin/docs/init_project_configuration.md b/rush-plugins/rush-init-project-plugin/docs/init_project_configuration.md new file mode 100644 index 0000000..712c632 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/docs/init_project_configuration.md @@ -0,0 +1,551 @@ +# Configuration to manage templates +You can create a configuration file called `template.json` with your templates. + +For instance, + +``` +common/_templates +├── rush-plugin-for-command +└── template.json +``` + +For `template.json` +``` +{ + "templates": [ + { + "displayName": "command template", + "templateFolder": "rush-plugin-for-command", // relative to template.json + } + ], + "globalPluginEntryPoint": "_globalPlugin/index.ts" // a global plugin +} +``` +# Configuration for initialize project + +You can create a configuration file called `init.config.js` or `init.config.ts` under your template folder. + +For instance, + +``` +common/_templates +└── rush-plugin-for-command + ├── README.md + ├── init.config.js // <--- + ├── init.config.ts // <--- +``` + +## Example for JavaScript configuration file: + +```javascript +/** @type {import('../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin').IConfig} */ +const config = { + prompts: [], + plugins: [], + defaultProjectConfiguration: {}, +}; +module.exports = config; +``` + +The comment contains `@types` tell your IDE where is the type of configuration. + +NOTE: you should replace `autoinstallers/command-plugins` with a real directory `autoinstallers/` + +## Example for TypeScript configuration file: + +```typescript +import type { IConfig } from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin"; + +const config: IConfig = { + prompts: [], + plugins: [], + defaultProjectConfiguration: {}, +}; + +export default config; +``` + +❗️❗️❗️ **NOTE**: + +1. You should install `typescript` as a dependencies in according autoinstaller +2. You should replace `autoinstallers/command-plugins` with a real directory `autoinstallers/` to make type works. +Or, you can add a `tsconfig.json` file under your `common/_templates/_plugins` folder and set up `paths` to make type works. + +e.g. + +**common/autoinstallers/command-plugins/package.json** + +```json +{ + "name": "command-plugins", + "version": "1.0.0", + "private": true, + "dependencies": { + "rush-init-project-plugin": "0.1.1", + "typescript": "4.4.2" + } +} +``` + +**common/_templates/_plugins/tsconfig.json** + +```json +{ + "compilerOptions": { + "paths": { + "rush-init-project-plugin": ["../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin"], + } + } +} +``` + +**common/_templates/_plugins/demoPlugin.ts** + +```typescript +import type { IConfig, IPlugin } from 'rush-init-project-plugin'; +``` + + +❗️❗️❗️ + +# `prompts` + +prompts is a list of `PromptQuestion`. The will be appended to internal questions, and prompt user to answer them. + +e.g. + +```javascript +const config = { + prompts: [ + { + type: "input", + name: "cdnHost", + message: "Input your CDN Host", + }, + ], +}; +``` + +then `cdnHost` is added to `answers`, and becomes one of the data when rendering template. That says `{{ cdnHost }}` in template file, will be replaced with the string user input. + +# `defaultProjectConfiguration` + +`defaultProjectConfiguration` is used to specify the project configuration in `rush.json` + +For example, + +```typescript +import type { + IConfig, + IHooks, + IPluginContext, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin"; + +const config: IConfig = { + defaultProjectConfiguration: { + reviewCategory: "libraries", + }, +}; + +export default config; +``` + +The initialized project configuration is `rush.json` will be + +```json +{ + "projects": [ + { + "packageName": "", + "projectFolder": "", + "reviewCategory": "libraries" // <--- comes from defaultProjectConfiguration + } + ] +} +``` + +## `defaultProjectConfiguration` properties + +Current defaultProjectConfiguration supports the following properties: + +- `reviewCategory` +- `decoupledLocalDependencies` +- `shouldPublish` +- `skipRushCheck` +- `versionPolicyName` +- `publishFolder` +- `tags` + +Please check [Rush documentation](https://rushjs.io/pages/configs/rush_json/) for more details. + +# `plugins` + +For flexibility, a tiny plugin system is created inside this plugin (Yes! Yet another plugin system upon rush plugin system) + +A plugin instance is JavaScript object which has an `apply` method. The method is called by this plugin, giving extensibility of initialization process. + +## Plugin Usage + +```typescript +import type { + IConfig, + IHooks, + IPluginContext, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin"; + +const config: IConfig = { + prompts: [], + plugins: [ + { + apply: (hooks: IHooks, pluginContext: IPluginContext) => { + // plugin logic here + }, + }, + ], +}; + +export default config; +``` + +You can also extract plugin logic and reuse it across multiple configuration file. + +```typescript +import type { + IConfig, + IHooks, + IPluginContext, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin"; +import { CDNPlugin } from "../_plugins/cdn-plugin"; + +const config: IConfig = { + prompts: [], + plugins: [new CDNPlugin()], +}; + +export default config; +``` + +```typescript +import type { + IPlugin, + IHooks, + IPromptsHookParams, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin/lib"; + +export class CDNPlugin implements IPlugin { + apply(hooks: IHooks): void { + hooks.prompts.tap("CDNPlugin", (prompts: IPromptsHookParams) => { + // unshift make this question prompt to user just after template is answered. + prompts.promptQueue.unshift({ + type: "input", + name: "cdnHost", + message: "Input your CDN host", + }); + }); + } +} +``` + +Now, the former functionality is extracted to a individual file at `common/_templates/_plugins/cdn-plugin.ts`. + +Thus, plugins can be used across templates. + +> NOTE: The folders startsWith `_` are not treated as template folder. No worries :) + +## Plugin Hooks + +The plugin system is based on `tapable`, if you are familiar with `webpack` plugin, it's pretty easy to follow. + +Plugin hooks Workflow: + +``` +┌─────────────────────────────┐ +│ │ +│ Load Global Configuration │ +│ `globalPluginEntryPoint` │ +│ in `template.json` │ +│ │ +└──────────────┬──────────────┘ + │ +┌──────────────▼───────────────┐ +│ Apply global plugin │ +└──────────────┬───────────────┘ + │ +┌──────────────▼─────────────────────────┐ +│ hooks.templates.promise({ templates }) │ +└──────────────┬─────────────────────────┘ + │ +┌──────────────▼──────────────┐ +│ │ +│ prompt to select a template │ +│ │ +└──────────────┬──────────────┘ + │ + │ +┌──────────────▼──────────────────────┐ +│ │ +│ Load Configuration │ +│ /init.config.[js|ts] │ +│ │ +└──────────────┬──────────────────────┘ + │ + │ +┌──────────────▼────────────────────┐ +│ Apply plugins in a sequence order │ +└──────────────┬────────────────────┘ + │ + │ +┌──────────────▼──────────┐ +│ hooks.plop.call(plop) │ +└──────────────┬──────────┘ + │ + │ +┌──────────────▼─────────────────────────┐ +│ hooks.prompts.promise({ promptQueue }) │ +└──────────────┬─────────────────────────┘ + │ + │ + │ +┌──────────────▼───────────────────────┐ +│ hooks.promptQuestion ◄───┐ +│ .get(currentPrompt.name) │ │ +│ .call(currentPrompt, answerSoFar) │ │ +└──────────────┬─────────────┬─────────┘ │ + │ │ │ + │ └─────────────┘ + │ + │ +┌──────────────▼────────────────────┐ +│ hooks.answers.promise(allAnswers) │ +└──────────────┬────────────────────┘ + │ + │ +┌──────────────▼──────────────────┐ +│ hooks.actions.call({ actions }) │ +└─────────────────────────────────┘ + │ + │ +┌──────────────▼──────────────────────┐ +│ hooks.done.promise(result, answers) │ +└─────────────────────────────────────┘ +``` + +### templates + +- AsyncSeriesHook +- params: `ITemplatesHook` + - { templates: ITemplatePathNameType[] } + +`templates` is internal templates list, and templates will show in choosing a template step. + +It only works in global plugin, and mutate the `templates` you can manage templates locally. + +### prompts + +- AsyncSeriesHook +- params: `IPromptsHookParams` + - { promptQueue: PromptQuestion[] } + +`promptQueue` is internal queue of prompt question. and question will be prompt to use in sequence order. + +Mutate the `promptQueue` makes you access the whole prompt process in initialization. + +### promptQuestion + +- HookMap +- Each hook params: `promptQuestion`, `answersSoFar` + +Hooks inside a HookMap is dynamically created in runtime. You can use `hooks.promptQuestion.for('projectFolder')` to get the hook for `projectFolder` prompt question. + +and then, use `tap` to access the original promptQuestion and answers so far + +e.g. + +```typescript +hooks.promptQuestion + .for("projectFolder") + .tap("yourPluginName", (promptQuestion, answersSoFar) => { + // logic here + }); +``` + +You can mutate `promptQuestion` and `answersSoFar`. + +And, if the callback function returns `null`, this question will be no longer prompt to user. + +### actions + +- SyncHook +- params: `IActionsHookParams` + - { actions: ActionType[] } + +`actions` are extra actions will be registered into plop. + +See [plop#ActionConfig](https://github.com/plopjs/plop#interface-actionconfig) for detail. + +default actions as follow: + +- `addProjectToRushJson` +- `runRushUpdate` +- `sortPackageJson` +- [plop built-in actions](https://github.com/plopjs/plop#built-in-actions) + +### answers + +- AsyncSeriesHook +- Params: `Answers` + +`answers` is all answers collected after the end of prompts. You can mutate answers in this hook. Since this object is used as handlebars data. You can inject more template data information into this object as well. + +### defaultProjectConfiguration + +- SyncHook +- Params: `IDefaultProjectConfiguration`, `Answers` + - `({ // defaultProjectConfiguration }, { // answers }` + +`defaultProjectConfiguration` with all answers is passed. You can mutate `defaultProjectConfiguration` here. + +### plop + +- SyncHook +- Params: `NodePlopAPI` + +This hooks exposes the internal `plop` API. + +### done + +- AsyncSeriesHook +- Params: `IResult`, `Answers` + +1. IResult = 'Failed' | 'Succeeded' +2. `Answers` is all answers collected after the end of prompts. + +# How to develop a plugin + +## Case 1: Add a new prompt question called `needCreateFoo` + +```typescript +import type { + IPlugin, + IHooks, + IPromptsHookParams, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin/lib"; + +export class FooPlugin implements IPlugin { + apply(hooks: IHooks): void { + hooks.prompts.tap("CDNPlugin", (prompts: IPromptsHookParams) => { + prompts.promptQueue.push({ + type: "confirm", + name: "needCreateFoo", + message: "Do you need create foo?", + }); + }); + } +} +``` + +## Case 2: Add a custom action and run depends on `needCreateFoo` + +```typescript +import type { + IPlugin, + IHooks, + IPromptsHookParams, + IAnswers, +} from "../../autoinstallers/command-plugins/node_modules/rush-init-project-plugin/lib"; + +interface IAnswersWithFoo extends IAnswers { + needCreateFoo?: boolean; +} + +export class FooPlugin implements IPlugin { + apply(hooks: IHooks): void { + /// ...snip + + // create a custom action called `createFoo` + hooks.plop.tap("FooPlugin", (plop) => { + plop.setActionType("createFoo", async (_ans: any) => { + const answers = _ans as IAnswersWithFoo; + if (!answers.needCreateFoo) { + return "Skip create foo"; + } + // do create foo logic + return "Create foo successfully"; + }); + }); + + // push `createFoo` action into plop actions + hooks.actions.tap("FooPlugin", ({ actions }) => { + actions.push({ + type: "createFoo", + }); + }); + } +} +``` + +## Case 3: Replace render engine with [ejs](https://www.npmjs.com/package/ejs) + +```typescript +import ejs from 'ejs'; +import type { IAnswers, IPlugin, IHooks, IPromptsHookParams } from 'rush-init-project-plugin'; + +export class EJSPlugin implements IPlugin { + public static readonly pluginName: string = 'ejsPlugin'; + apply(hooks: IHooks): void { + hooks.plop.tap(EJSPlugin.pluginName, (plop) => { + plop.renderString = (template: string, data: IAnswers) => { + return ejs.render(template, data); + } + }); + }; +} +``` + +NOTE: `ejs` is installed by `autoinstaller` + +```json +// common/autoinstallers/command-plugins/package.json +{ + "dependencies": { + "ejs": "3.8.1" + } +} +``` + +## Case 4: Add predefined variables to template + +```typescript +import type { IAnswers, IPlugin, IHooks, IPromptsHookParams } from 'rush-init-project-plugin'; + +export class MyDataPlugin implements IPlugin { + public static readonly pluginName: string = 'MyDataPlugin'; + apply(hooks: IHooks): void { + hooks.answers.tap(MyDataPlugin.pluginName, (answers) => { + // mutate answers here + answers.foo = 'foo'; + answers.bar = 'bar'; + }); + }; +} +``` + +## Case 5: Report init-project usage to telemetry server + +```typescript +import type { IAnswers, IPlugin, IHooks, IResult } from 'rush-init-project-plugin'; + +export class MyTelemetryPlugin implements IPlugin { + apply(hooks: IHooks): void { + hooks.done.tapPromise("my-telemetry-plugin", async (result: IResult, answers: IAnswers) => { + // report to telemetry server... + await new Promise((resolve) => { + setTimeout(() => { + console.log(result, answers); + }, 1000); + resolve(); + }); + }); + }; +} +``` \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/lint-staged.config.cjs b/rush-plugins/rush-init-project-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-init-project-plugin/package.json b/rush-plugins/rush-init-project-plugin/package.json new file mode 100644 index 0000000..0f30606 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/package.json @@ -0,0 +1,66 @@ +{ + "name": "rush-init-project-plugin", + "version": "0.9.0", + "description": "Rush plugin for initialize project in monorepo", + "keywords": [ + "rush", + "plugin", + "command", + "init", + "project" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-init-project-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "bin": { + "rush-init-project": "lib/cli.js" + }, + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "@types/inquirer-autocomplete-prompt": "~3.0.0", + "blessed": "~0.1.81", + "blessed-contrib": "~4.11.0", + "chalk": "4.1.2", + "commander": "~9.4.0", + "handlebars-helpers": "~0.10.0", + "inquirer": "~8.2.0", + "inquirer-autocomplete-prompt": "~1.4.0", + "lilconfig": "~2.0.4", + "lodash": "4.17.21", + "node-plop": "0.26.3", + "ora": "5.4.1", + "sort-package-json": "1.54.0", + "tapable": "~2.2.1", + "ts-node": "~10.4.0", + "validate-npm-package-name": "~3.0.0" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-jest-plugin": "~0.1.53", + "@rushstack/heft-node-rig": "1.2.31", + "@types/blessed": "~0.1.19", + "@types/ejs": "~3.1.1", + "@types/heft-jest": "1.0.1", + "@types/inquirer": "~8.1.3", + "@types/lodash": "4.14.184", + "@types/node": "12.20.24", + "del": "6.1.1", + "ejs": "~3.1.8", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json b/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..2d39526 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-init-project-plugin", + "description": "Rush plugin for initialize project in monorepo", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-init-project-plugin/src/actions/addProjectToRushJson.ts b/rush-plugins/rush-init-project-plugin/src/actions/addProjectToRushJson.ts new file mode 100644 index 0000000..1859462 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/actions/addProjectToRushJson.ts @@ -0,0 +1,33 @@ +import { JsonFile, JsonObject } from "@rushstack/node-core-library"; +import { loadRushConfiguration } from "../logic/loadRushConfiguration"; + +import type { RushConfiguration } from "@rushstack/rush-sdk"; +import type { IDefaultProjectConfiguration } from "../logic/TemplateConfiguration"; + +export interface IAddProjectToRushJsonParams { + packageName: string; + projectFolder: string; + defaultProjectConfiguration?: IDefaultProjectConfiguration; +} + +export const addProjectToRushJson = ({ + packageName, + projectFolder, + defaultProjectConfiguration = {}, +}: IAddProjectToRushJsonParams): void => { + const rushConfiguration: RushConfiguration = + loadRushConfiguration() as unknown as RushConfiguration; + const { rushJsonFile } = rushConfiguration; + const rawRushConfigJson: JsonObject = JsonFile.load(rushJsonFile); + const projectConfiguration: JsonObject = { + packageName, + projectFolder, + ...defaultProjectConfiguration, + }; + rawRushConfigJson.projects.push({ + ...projectConfiguration, + }); + JsonFile.save(rawRushConfigJson, rushJsonFile, { + updateExistingFile: true, + }); +}; diff --git a/rush-plugins/rush-init-project-plugin/src/actions/rushRushUpdate.ts b/rush-plugins/rush-init-project-plugin/src/actions/rushRushUpdate.ts new file mode 100644 index 0000000..ef5cd4a --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/actions/rushRushUpdate.ts @@ -0,0 +1,15 @@ +import { Executable } from "@rushstack/node-core-library"; +import type { SpawnSyncReturns } from "child_process"; + +export const runRushUpdate = (): void => { + const result: SpawnSyncReturns = Executable.spawnSync( + "rush", + ["update"], + { + stdio: "inherit", + } + ); + if (result.status !== 0) { + throw new Error('Run "rush update" failed'); + } +}; diff --git a/rush-plugins/rush-init-project-plugin/src/actions/sortPackageJson.ts b/rush-plugins/rush-init-project-plugin/src/actions/sortPackageJson.ts new file mode 100644 index 0000000..846be27 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/actions/sortPackageJson.ts @@ -0,0 +1,19 @@ +import * as path from "path"; +import { FileSystem } from "@rushstack/node-core-library"; +import sort from "sort-package-json"; +import { loadRushConfiguration } from "../logic/loadRushConfiguration"; + +export const sortPackageJson = (projectFolder: string): void => { + const { rushJsonFolder } = loadRushConfiguration(); + const packageJsonPath: string = path.join( + rushJsonFolder, + projectFolder, + "package.json" + ); + if (!FileSystem.exists(packageJsonPath)) { + throw new Error(`package.json for ${projectFolder} does not exist`); + } + + const input: string = FileSystem.readFile(packageJsonPath); + FileSystem.writeFile(packageJsonPath, sort(input)); +}; diff --git a/rush-plugins/rush-init-project-plugin/src/cli.ts b/rush-plugins/rush-init-project-plugin/src/cli.ts new file mode 100644 index 0000000..382fff9 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/cli.ts @@ -0,0 +1,38 @@ +#!/usr/bin/env node + +import { Terminal } from '@rushstack/node-core-library'; +import { program } from 'commander'; +import { initProject } from './init-project'; +import { getTemplatesFolderAndValidate } from './logic/templateFolder'; +import { TerminalSingleton } from './terminal'; + +(async () => { + program + .option('-a, --answer ', 'Provide predefined answers with JSON string') + .option('-d, --dry-run', 'Provide the option isDryRun in plugin context', false) + .option('-v, --verbose', 'Enable output verbose debug purposing messages', false) + .option('--ui', 'Provide terminal ui operation', false) + .description('Initialize new Rush projects') + .action(async (params) => { + TerminalSingleton.setVerboseEnabled(params?.verbose ?? false); + const terminal: Terminal = TerminalSingleton.getInstance(); + try { + await getTemplatesFolderAndValidate(); + await initProject(params); + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } + }); + + program.on('command:*', () => { + console.error('undefined command', program.args.join(' ')); + process.exit(1); + }); + + await program.parseAsync(process.argv); +})().catch((e) => (e?.message ? console.error(e.message) : console.error(e))); diff --git a/rush-plugins/rush-init-project-plugin/src/hooks.ts b/rush-plugins/rush-init-project-plugin/src/hooks.ts new file mode 100644 index 0000000..a76c560 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/hooks.ts @@ -0,0 +1,64 @@ +import { AsyncSeriesHook, HookMap, SyncHook } from 'tapable'; + +import type { ActionType, NodePlopAPI, PromptQuestion } from 'node-plop'; +import type { IDefaultProjectConfiguration } from './logic/TemplateConfiguration'; +import type { IExtendedAnswers } from './plopfile'; +import type { ITemplatePathNameType } from './logic/templateFolder'; + +export interface ITemplatesHook { + templates: ITemplatePathNameType[]; +} + +export interface IPromptsHookParams { + /** + * The queue of prompt question. and question will be prompt to use in sequence order + */ + promptQueue: PromptQuestion[]; +} + +export interface IActionsHookParams { + /** + * A list of plop action. These actions will be registered into plop + */ + actions: ActionType[]; +} + +type IAnswers = IExtendedAnswers; + +export type IResult = 'Succeeded' | 'Failed'; + +export interface IHooks { + templates: AsyncSeriesHook; + prompts: AsyncSeriesHook; + actions: SyncHook; + answers: AsyncSeriesHook; + plop: SyncHook; + promptQuestion: HookMap>; + defaultProjectConfiguration: SyncHook<[IDefaultProjectConfiguration, IAnswers]>; + done: AsyncSeriesHook<[IResult, IAnswers]>; +} + +const initHooks = (): IHooks => { + return { + templates: new AsyncSeriesHook(['templates']), + prompts: new AsyncSeriesHook(['promptsHookParams']), + answers: new AsyncSeriesHook(['answers']), + actions: new SyncHook(['actionsHookParams']), + plop: new SyncHook(['plop']), + promptQuestion: new HookMap( + (key: string) => + new SyncHook<[PromptQuestion, IAnswers], null | undefined>(['promptQuestion', 'answersSoFar']) + ), + defaultProjectConfiguration: new SyncHook<[IDefaultProjectConfiguration, IAnswers]>([ + 'defaultProjectConfiguration', + 'answers' + ]), + done: new AsyncSeriesHook<[IResult, IAnswers]>(['result', 'answers']) + }; +}; + +const hooks: IHooks = initHooks(); + +export const getHooks: () => IHooks = (): IHooks => { + return hooks; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/index.ts b/rush-plugins/rush-init-project-plugin/src/index.ts new file mode 100644 index 0000000..5209154 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/index.ts @@ -0,0 +1,10 @@ +export type { + IPlugin, + IConfig, + IPluginContext, + IDefaultProjectConfiguration, +} from "./logic/TemplateConfiguration"; +export type { IHooks, IActionsHookParams, IPromptsHookParams, IResult } from "./hooks"; +export type { NodePlopAPI, PromptQuestion } from "node-plop"; +export type { IExtendedAnswers as IAnswers } from "./plopfile"; +export * from "./terminal"; diff --git a/rush-plugins/rush-init-project-plugin/src/init-project.ts b/rush-plugins/rush-init-project-plugin/src/init-project.ts new file mode 100644 index 0000000..2076006 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/init-project.ts @@ -0,0 +1,110 @@ +import { Colors, Terminal } from '@rushstack/node-core-library'; +import chalk from 'chalk'; +import type { NodePlopAPI, PlopGenerator } from 'node-plop'; +import nodePlop from 'node-plop'; +import ora, { Ora } from 'ora'; +import * as path from 'path'; +import { getHooks, IHooks, IResult } from './hooks'; +import type { IExtendedAnswers } from './plopfile'; +import { TerminalSingleton } from './terminal'; + +export interface ICliParams { + answer?: string | Record; + verbose: boolean; + dryRun: boolean; + ui: boolean; +} + +export const initProject = async (params: ICliParams): Promise => { + const terminal: Terminal = TerminalSingleton.getInstance(); + // validate if external answer is valid JSON + if (params.answer && typeof params.answer === 'string') { + try { + params.answer = JSON.parse(params.answer); + } catch (error: any) { + params.answer = ''; + terminal.writeErrorLine(`Invalid JSON answer: ${error?.message}`); + } + } + const plopfilePath: string = path.join(__dirname, './plopfile.js'); + + const plop: NodePlopAPI = nodePlop(plopfilePath, { + destBasePath: process.cwd(), + force: false, + ...params + }); + + const generators: { name: string; description: string }[] = plop.getGeneratorList(); + + if (generators.length !== 1) { + throw new Error('It should never run into this line. Please report to the author.'); + } + + const generator: PlopGenerator = plop.getGenerator(generators[0].name); + await doThePlop(generator, []); + + TerminalSingleton.getInstance().writeLine(Colors.green('ALL DONE!')); +}; + +async function doThePlop(generator: PlopGenerator, bypassArr: string[]): Promise { + const hooks: IHooks = getHooks(); + const spinner: Ora = ora(); + const answers: IExtendedAnswers = await generator.runPrompts(bypassArr); + const noMap: boolean = false; + let failedActions: boolean = false; + await generator.runActions(answers, { + onComment: (msg) => { + spinner.info(msg); + spinner.start(); + }, + onSuccess: (change) => { + let line: string = ''; + if (change.type) { + line += ` ${typeMap(change.type, noMap)}`; + } + if (change.path) { + line += ` ${change.path}`; + } + spinner.succeed(line); + spinner.start(); + }, + onFailure: (failure) => { + let line: string = ''; + if (failure.type) { + line += ` ${typeMap(failure.type, noMap)}`; + } + if (failure.path) { + line += ` ${failure.path}`; + } + const errMsg: string = failure.error || failure.message; + if (errMsg) { + line += ` ${errMsg}`; + } + spinner.fail(line); + failedActions = true; + spinner.start(); + } + }); + spinner.stop(); + const result: IResult = failedActions ? 'Failed' : 'Succeeded'; + await hooks.done.promise(result, answers); + if (failedActions) { + throw new Error('Failed to init project'); + } +} + +const typeDisplay: Record = { + function: chalk.yellow('->'), + add: chalk.green('++'), + addMany: chalk.green('+!'), + modify: `${chalk.green('+')}${chalk.red('-')}`, + append: chalk.green('_+'), + skip: chalk.green('--') +}; +function typeMap(name: string, noMap: boolean): string { + const dimType: string = chalk.dim(name); + if (!noMap && name in typeDisplay) { + return typeDisplay[name as keyof typeof typeDisplay]; + } + return dimType; +} diff --git a/rush-plugins/rush-init-project-plugin/src/logic/GitConfig.ts b/rush-plugins/rush-init-project-plugin/src/logic/GitConfig.ts new file mode 100644 index 0000000..12004d7 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/GitConfig.ts @@ -0,0 +1,22 @@ +import { Executable } from "@rushstack/node-core-library"; +import type { SpawnSyncReturns } from "child_process"; + +export const getGitUserName = (cwd: string): string => { + try { + const result: SpawnSyncReturns = Executable.spawnSync( + 'git', + ['config', 'user.name'], + { + currentWorkingDirectory: cwd, + stdio: "pipe", + } + ); + if (result.status !== 0) { + return ''; + } + return result.stdout?.trim() ?? ''; + } catch (e) { + // no-catch + return ''; + } +} \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/src/logic/TemplateConfiguration.ts b/rush-plugins/rush-init-project-plugin/src/logic/TemplateConfiguration.ts new file mode 100644 index 0000000..26ed644 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/TemplateConfiguration.ts @@ -0,0 +1,116 @@ +import type { PromptQuestion } from "node-plop"; +import { getTemplateFolder } from "./templateFolder"; +import { lilconfigSync, LilconfigResult } from "lilconfig"; +import type { IHooks } from "../hooks"; + +const searchPlaces: string[] = ["init.config.ts", "init.config.js"]; + +const loaders: Record IConfig> = { + ".js": (path) => require(path), + ".ts": (path) => { + require("ts-node").register({ + transpileOnly: true, + compilerOptions: { + esModuleInterop: true, + }, + }); + const module: any = require(path); + try { + if ("default" in module) { + return module.default; + } + } catch { + // no-catch + } + return module; + }, +}; + +/** + * See https://rushjs.io/pages/configs/rush_json/ + */ +export interface IDefaultProjectConfiguration { + reviewCategory?: string; + /** + * @deprecated Use `decoupledLocalDependencies` instead. + */ + cyclicDependencyProjects?: string[]; + decoupledLocalDependencies?: string[]; + shouldPublish?: boolean; + skipRushCheck?: boolean; + versionPolicyName?: string; + publishFolder?: string; + tags?: string[]; +} + +export interface IConfig { + prompts?: PromptQuestion[]; + plugins?: IPlugin[]; + defaultProjectConfiguration?: IDefaultProjectConfiguration; + displayName?: string; +} + +export interface IPlugin { + apply: (hook: IHooks, pluginContext: IPluginContext) => void; +} + +export interface IPluginContext extends Record { + isDryRun: boolean; + cliAnswer: Record; +} + +export class TemplateConfiguration { + private _prompts: PromptQuestion[]; + private _plugins: IPlugin[]; + private _defaultProjectConfiguration: IDefaultProjectConfiguration; + public displayName: string; + + private constructor(template: string) { + const templateFolder: string = getTemplateFolder(template); + const result: LilconfigResult = lilconfigSync("init", { + searchPlaces, + loaders, + }).search(templateFolder); + this._prompts = []; + this._plugins = []; + this._defaultProjectConfiguration = {}; + this.displayName = ""; + if (result && result.config) { + if (result.config.prompts) { + this._prompts = result.config.prompts; + } + if (result.config.plugins) { + this._plugins = result.config.plugins; + } + if (result.config.defaultProjectConfiguration) { + this._defaultProjectConfiguration = + result.config.defaultProjectConfiguration; + } + if (result.config.displayName) { + this.displayName = result.config.displayName; + } + } + } + public static async loadFromTemplate( + template: string + ): Promise { + if (!template) { + throw new Error( + "template is required when loading template configuration" + ); + } + return new TemplateConfiguration(template); + } + + public get prompts(): PromptQuestion[] { + return this._prompts; + } + + public get plugins(): IPlugin[] { + return this._plugins; + } + + public get defaultProjectConfiguration(): IDefaultProjectConfiguration { + return this._defaultProjectConfiguration; + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/logic/loadGlobalConfiguration.ts b/rush-plugins/rush-init-project-plugin/src/logic/loadGlobalConfiguration.ts new file mode 100644 index 0000000..301a73e --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/loadGlobalConfiguration.ts @@ -0,0 +1,74 @@ +import * as path from 'path'; +import { LilconfigResult, lilconfigSync } from 'lilconfig'; +import { FileSystem, Terminal, JsonFile, JsonSchema, JsonObject } from '@rushstack/node-core-library'; +import templeteSchema from './template.schema.json'; +import { TerminalSingleton } from '../terminal'; +import { getTemplatesFolder, getTemplateNameList, ITemplatePathNameType } from './templateFolder'; +import { IHooks } from '../hooks'; +import { IPluginContext } from './TemplateConfiguration'; + +export interface IGlobalConfig { + templateNameList: ITemplatePathNameType[]; +} + +const globalPluginLoaders: Record void> = { + '.js': (path) => require(path), + '.ts': (path) => { + require('ts-node').register({ + transpileOnly: true, + compilerOptions: { + esModuleInterop: true + } + }); + const module: any = require(path); + try { + if ('default' in module) { + return module.default; + } + } catch { + // no-catch + } + return module; + } +}; + +// global configuration will load config from `template.json` +export async function loadGlobalConfiguration( + hooks: IHooks, + pluginContext: IPluginContext +): Promise { + const terminal: Terminal = TerminalSingleton.getInstance(); + const templateFolder: string = getTemplatesFolder(); + const templateConfigPath: string = path.join(templateFolder, 'template.json'); + // if template.json doesn't exists, get the template list from folder + if (!FileSystem.exists(templateConfigPath)) { + return { + templateNameList: getTemplateNameList(templateFolder) + }; + } + const jsonSchema: JsonSchema = JsonSchema.fromLoadedObject(templeteSchema); + const res: JsonObject = await JsonFile.loadAndValidateWithCallbackAsync( + templateConfigPath, + jsonSchema, + ({ details = '' }): void => { + terminal.writeErrorLine(details); + process.exit(1); + } + ); + const { templates, globalPluginEntryPoint } = res; + if (globalPluginEntryPoint) { + const result: LilconfigResult = lilconfigSync('init', { + searchPlaces: [globalPluginEntryPoint], + loaders: globalPluginLoaders + }).search(templateFolder); + if (result) { + for (const plugin of result.config?.plugins) { + plugin.apply(hooks, pluginContext); + } + } + } + + return { + templateNameList: templates as ITemplatePathNameType[] + }; +} diff --git a/rush-plugins/rush-init-project-plugin/src/logic/loadRushConfiguration.ts b/rush-plugins/rush-init-project-plugin/src/logic/loadRushConfiguration.ts new file mode 100644 index 0000000..f241672 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/loadRushConfiguration.ts @@ -0,0 +1,23 @@ +import { RushConfiguration } from "@rushstack/rush-sdk"; + +const cwd2RushConfiguration: Record = {}; + +export const loadRushConfiguration = ( + cwd: string = process.cwd() +): RushConfiguration => { + let rushConfiguration: RushConfiguration = cwd2RushConfiguration[cwd]; + if (!rushConfiguration) { + try { + rushConfiguration = RushConfiguration.loadFromDefaultLocation({ + startingFolder: cwd, + }); + if (!rushConfiguration) { + throw new Error("Rush configuration not found"); + } + cwd2RushConfiguration[cwd] = rushConfiguration; + } catch (e) { + throw new Error("Load rush configuration failed"); + } + } + return rushConfiguration; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/logic/template.schema.json b/rush-plugins/rush-init-project-plugin/src/logic/template.schema.json new file mode 100644 index 0000000..9136b82 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/template.schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Template config File", + "description": "The main configuration file Template management.", + "type": "object", + "properties": { + "$schema": { + "description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.", + "type": "string" + }, + "templates": { + "description": "A list of templates managed by this tool.", + "type": "array", + "items": { + "type": "object", + "properties": { + "displayName": { + "description": "The display name of the template.", + "type": "string" + }, + "templateFolder": { + "description": "The path to the template folder relative to the template config file.", + "type": "string" + } + }, + "additionalProperties": false, + "required": ["templateFolder"] + } + }, + "globalPluginEntryPoint": { + "description": "entry point for global plugins", + "type": "string" + } + }, + "additionalProperties": false, + "required": ["templates"] +} diff --git a/rush-plugins/rush-init-project-plugin/src/logic/templateFolder.ts b/rush-plugins/rush-init-project-plugin/src/logic/templateFolder.ts new file mode 100644 index 0000000..38cfe07 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/logic/templateFolder.ts @@ -0,0 +1,55 @@ +import * as path from 'path'; +import { FileSystem } from '@rushstack/node-core-library'; +import { loadRushConfiguration } from './loadRushConfiguration'; + +export interface ITemplatePathNameType { + templateFolder: string; + displayName?: string; +} + +const templatesFolder2templateNameList: Record> = {}; + +export const getTemplatesFolder = (): string => { + const { commonFolder } = loadRushConfiguration(); + const templatesFolder: string = path.join(commonFolder, '_templates'); + return templatesFolder; +}; + +export const getTemplatesFolderAndValidate = (): string => { + const templatesFolder: string = getTemplatesFolder(); + if (!FileSystem.exists(templatesFolder)) { + FileSystem.ensureFolder(templatesFolder); + throw new Error(`Templates folder created, please setup template under "${templatesFolder}"`); + } + + const templateNameList: ITemplatePathNameType[] = getTemplateNameList(templatesFolder); + if (templateNameList.length === 0) { + throw new Error(`Please setup template under ${templatesFolder}`); + } + + return templatesFolder; +}; + +// get template list from folder +export function getTemplateNameList(templatesFolder: string): ITemplatePathNameType[] { + let templateNameList: ITemplatePathNameType[] = templatesFolder2templateNameList[templatesFolder]; + if (!templateNameList) { + const templateFolderList: string[] = FileSystem.readFolder(templatesFolder) + .filter((filename: string) => { + return FileSystem.getStatistics(path.resolve(templatesFolder, filename)).isDirectory(); + }) + .filter((filename: string) => { + return !filename.startsWith('_'); + }); + templateNameList = templateFolderList.map((templateFolder: string) => ({ templateFolder })); + } + // eslint-disable-next-line require-atomic-updates + templatesFolder2templateNameList[templatesFolder] = templateNameList; + return templateNameList; +} + +export function getTemplateFolder(template: string): string { + const templatesFolder: string = getTemplatesFolder(); + const templateFolder: string = path.join(templatesFolder, template); + return templateFolder; +} diff --git a/rush-plugins/rush-init-project-plugin/src/plopfile.ts b/rush-plugins/rush-init-project-plugin/src/plopfile.ts new file mode 100644 index 0000000..df44cda --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/plopfile.ts @@ -0,0 +1,337 @@ +import type { RushConfiguration } from '@rushstack/rush-sdk'; +import { FileSystem, PackageName, Terminal } from '@rushstack/node-core-library'; +import hbsHelpersLib from 'handlebars-helpers/lib'; +import { Answers, Inquirer } from 'inquirer'; +import autocompletePlugin from 'inquirer-autocomplete-prompt'; +import { pickBy } from 'lodash'; +import type { + ActionConfig, + ActionType, + DynamicPromptsFunction, + NodePlopAPI, + PlopCfg, + PromptQuestion +} from 'node-plop'; +import * as path from 'path'; +import type { SyncHook } from 'tapable'; +import validatePackageName from 'validate-npm-package-name'; +import { addProjectToRushJson } from './actions/addProjectToRushJson'; +import { runRushUpdate } from './actions/rushRushUpdate'; +import { sortPackageJson } from './actions/sortPackageJson'; +import { IHooks, getHooks } from './hooks'; +import { loadRushConfiguration } from './logic/loadRushConfiguration'; +import { + IDefaultProjectConfiguration, + IPluginContext, + TemplateConfiguration +} from './logic/TemplateConfiguration'; +import { getTemplatesFolder } from './logic/templateFolder'; +import { getGitUserName } from './logic/GitConfig'; +import type { ICliParams } from './init-project'; +import { TerminalSingleton } from './terminal'; +import { IGlobalConfig, loadGlobalConfiguration } from './logic/loadGlobalConfiguration'; + +export interface IExtendedAnswers extends Answers { + authorName: string; + description: string; + template: string; + packageName: string; + unscopedPackageName: string; + projectFolder: string; + shouldRunRushUpdate: boolean; +} + +export default function (plop: NodePlopAPI, plopCfg: PlopCfg & ICliParams): void { + const terminal: Terminal = TerminalSingleton.getInstance(); + const rushConfiguration: RushConfiguration = loadRushConfiguration(); + const monorepoRoot: string = rushConfiguration.rushJsonFolder; + + const hooks: IHooks = getHooks(); + + const pluginContext: IPluginContext = { + isDryRun: plopCfg.dryRun || Boolean(process.env.DRY_RUN), + cliAnswer: typeof plopCfg.answer === 'object' ? plopCfg.answer : {} + }; + + registerActions(plop); + registerHelpers(plop); + + const defaultPrompts: PromptQuestion[] = [ + { + type: 'input', + name: 'authorName', + message: 'What is your name? (used in package.json)', + default() { + return getGitUserName(monorepoRoot).trim(); + }, + validate(input: string) { + return Boolean(input); + } + }, + { + name: 'packageName', + type: 'input', + message: `Input package name`, + async validate(input: string, answers: Partial) { + if (!input) { + return 'package name is required'; + } + if (!validatePackageName(input)) { + return 'package name is invalid'; + } + return true; + } + }, + { + type: 'input', + message: 'Input package description', + name: 'description', + validate: (input: string) => { + if (!input) { + return 'description is required'; + } + return true; + } + }, + { + type: 'input', + message: 'Input a relative path to store this project', + name: 'projectFolder', + validate: (input: string) => { + if (!input) { + return 'project folder is required'; + } + if (FileSystem.exists(path.join(monorepoRoot, input))) { + return 'project folder already exists, please delete it first'; + } + return true; + } + }, + { + type: 'confirm', + name: 'shouldRunRushUpdate', + message: 'Do you need run rush update after init?' + } + ]; + + // get template config when invoke loadTemplateConfiguration + let templateConfiguration: TemplateConfiguration | undefined; + const loadTemplateConfiguration: ( + promptQueue: PromptQuestion[], + template: string + ) => Promise = async (promptQueue, template) => { + templateConfiguration = await TemplateConfiguration.loadFromTemplate(template); + for (const prompt of templateConfiguration.prompts) { + promptQueue.push(prompt); + } + for (const plugin of templateConfiguration.plugins) { + plugin.apply(hooks, pluginContext); + } + hooks.plop.call(plop); + await hooks.prompts.promise({ + promptQueue + }); + }; + + const promptsFunc: DynamicPromptsFunction = async ( + inquirerPassed: Parameters[0] + ): Promise => { + const inquirer: Inquirer = inquirerPassed as unknown as Inquirer; + inquirer.registerPrompt('autocomplete', autocompletePlugin); + + const { templateNameList }: IGlobalConfig = await loadGlobalConfiguration(hooks, pluginContext); + + await hooks.templates.promise({ + templates: templateNameList + }); + + const templateChoices: { name: string; value: string }[] = templateNameList.map((x) => ({ + name: x.displayName ? x.displayName : x.templateFolder, + value: x.templateFolder + })); + + // default prompt + const defaultPromptFunc = async (): Promise => { + let allAnswers: Partial = {}; + defaultPrompts.unshift({ + type: 'autocomplete', + name: 'template', + message: 'Please select a template', + source: (ans: unknown, input: string) => { + if (!input) { + return templateChoices; + } + return templateChoices.filter((x) => x.name.includes(input) || x.value.includes(input)); + }, + loop: false, + pageSize: 20 + } as any); + + const promptQueue: PromptQuestion[] = defaultPrompts.slice(); + + // choose selected template + if (pluginContext.cliAnswer.template) { + allAnswers.template = pluginContext.cliAnswer.template; + } + + while (promptQueue.length > 0) { + const currentPrompt: PromptQuestion = promptQueue.shift()!; + + const hookForCurrentPrompt: + | SyncHook<[PromptQuestion, Partial], null | undefined> + | undefined = hooks.promptQuestion.get(currentPrompt.name); + if (hookForCurrentPrompt) { + const hookResult: null | undefined = hookForCurrentPrompt.call(currentPrompt, allAnswers); + // hook can return null to skip the prompt + if (hookResult === null) { + continue; + } + } + + // we don't need to filter prompts, for Inquirer will avoid asking allAnswers already provided here. + // https://github.com/SBoudrias/Inquirer.js#methods + const currentAnswers: Partial = await inquirer.prompt([currentPrompt], allAnswers); + + // when template decided, load template configuration + if (currentPrompt?.name === 'template') { + await loadTemplateConfiguration(promptQueue, currentAnswers.template!); + const promptQueueNames: Array = promptQueue.map((x) => x.name); + // apply cliAnswer + allAnswers = pickBy(pluginContext.cliAnswer, (v, k) => promptQueueNames.includes(k)); + } + // merge answers + allAnswers = { ...allAnswers, ...currentAnswers }; + } + return allAnswers; + }; + + // terminal ui logic + const invokeUI = async (): Promise => { + const { initBlessedForm } = await import('./ui'); + return await initBlessedForm( + defaultPrompts, + pluginContext, + plop, + plopCfg, + loadTemplateConfiguration, + templateChoices + ); + }; + + let promptAnswers: Answers; + + if (plopCfg.ui) { + promptAnswers = await invokeUI(); + } else { + promptAnswers = await defaultPromptFunc(); + } + // process answers + promptAnswers.unscopedPackageName = PackageName.getUnscopedName(promptAnswers.packageName ?? ''); + try { + await hooks.answers.promise(promptAnswers as IExtendedAnswers); + } catch (error: any) { + terminal.writeErrorLine(`Error in "answers" hook, please check your plugins`); + terminal.writeErrorLine((error ?? 'error')?.toString()); + process.exit(1); + } + return promptAnswers; + }; + + plop.setGenerator('rush-init-project', { + description: 'Rush init project', + prompts: promptsFunc, + actions: (answer) => { + const { template, projectFolder } = answer as IExtendedAnswers; + + const defaultProjectConfiguration: IDefaultProjectConfiguration = + templateConfiguration?.defaultProjectConfiguration || {}; + hooks.defaultProjectConfiguration.call(defaultProjectConfiguration, answer as IExtendedAnswers); + + const templatesFolder: string = getTemplatesFolder(); + // glob result is always splitted by slash + const baseFolder: string = path.join(templatesFolder, template).replace(/\\/g, '/'); + + const actions: ActionType[] = plopCfg.dryRun + ? [] + : [ + { + type: 'addMany', + destination: path.resolve(monorepoRoot, projectFolder), + base: baseFolder, + templateFiles: [`**/*`, '!init.config.ts', '!init.config.js'], + globOptions: { + cwd: baseFolder, + dot: true, + absolute: true + }, + data: answer + }, + { + type: 'sortPackageJson' + }, + { + type: 'addProjectToRushJson', + data: { + defaultProjectConfiguration + } + }, + { + type: 'runRushUpdate' + } + ]; + + hooks.actions.call({ actions }); + + return actions; + } + }); +} + +function registerActions(plop: NodePlopAPI): void { + plop.setActionType('addProjectToRushJson', (ans: Answers, config: ActionConfig | undefined) => { + const answers: IExtendedAnswers = ans as IExtendedAnswers; + const { packageName, projectFolder } = answers; + const defaultProjectConfiguration: IDefaultProjectConfiguration = + ( + config?.data as { + defaultProjectConfiguration: IDefaultProjectConfiguration; + } + )?.defaultProjectConfiguration || {}; + if (!packageName) { + throw new Error('packageName is required'); + } + if (!projectFolder) { + throw new Error('projectFolder is required'); + } + addProjectToRushJson({ + packageName, + projectFolder, + defaultProjectConfiguration + }); + return `Add ${packageName} to rush.json successfully`; + }); + + plop.setActionType('runRushUpdate', (ans: Answers) => { + const { shouldRunRushUpdate } = ans as IExtendedAnswers; + if (!shouldRunRushUpdate) { + return 'Skip "rush update", please run it manually'; + } + runRushUpdate(); + return 'Run rush update successfully'; + }); + + plop.setActionType('sortPackageJson', (ans: Answers) => { + const { projectFolder } = ans as IExtendedAnswers; + sortPackageJson(projectFolder); + return 'Sort package.json successfully'; + }); +} + +function registerHelpers(plop: NodePlopAPI): void { + // See https://github.com/helpers/handlebars-helpers/blob/master/README.md#helpers + for (const helpers of Object.values>(hbsHelpersLib)) { + for (const [helperName, helperFunc] of Object.entries(helpers)) { + plop.setHelper(helperName, helperFunc); + } + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/terminal.ts b/rush-plugins/rush-init-project-plugin/src/terminal.ts new file mode 100644 index 0000000..2ff96f7 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/terminal.ts @@ -0,0 +1,97 @@ +import { + ColorValue, + ConsoleTerminalProvider, + Terminal, + TextAttribute, +} from "@rushstack/node-core-library"; + +export class TerminalSingleton { + private static _instance: Terminal | undefined; + private static _terminalProvider: ConsoleTerminalProvider = + new ConsoleTerminalProvider(); + private constructor() {} + public static getInstance(): Terminal { + if (!TerminalSingleton._instance) { + TerminalSingleton._instance = new Terminal( + TerminalSingleton._terminalProvider + ); + } + return TerminalSingleton._instance; + } + public static setVerboseEnabled(enabled: boolean): void { + TerminalSingleton._terminalProvider.verboseEnabled = enabled; + } +} + +export interface ILogOption { + prefix: string; + verboseEnabled?: boolean; +} + +export interface ILogger { + info(msg: string): void; + warn(msg: string): void; + error(msg: string): void; + success(msg: string): void; + verbose(msg: string): void; +} + +export function createLog(logOption: ILogOption): ILogger { + const { prefix, verboseEnabled } = logOption; + // eslint-disable-next-line no-unused-expressions + if (typeof verboseEnabled === "boolean") + TerminalSingleton.setVerboseEnabled(verboseEnabled); + const terminal: Terminal = TerminalSingleton.getInstance(); + return { + info(msg: string) { + terminal.write({ + text: `${prefix} `, + backgroundColor: ColorValue.Blue, + foregroundColor: ColorValue.Black, + }); + terminal.writeLine({ + text: msg, + textAttributes: [TextAttribute.Dim], + }); + }, + warn(msg: string) { + terminal.write({ + text: `${prefix} `, + backgroundColor: ColorValue.Yellow, + foregroundColor: ColorValue.Black, + }); + terminal.writeLine({ + text: msg, + foregroundColor: ColorValue.Yellow, + }); + }, + error(msg: string) { + terminal.write({ + text: `${prefix} `, + foregroundColor: ColorValue.White, + backgroundColor: ColorValue.Red, + }); + terminal.writeLine({ + text: msg, + foregroundColor: ColorValue.Red, + }); + }, + success(msg: string) { + terminal.write({ + text: `${prefix} `, + foregroundColor: ColorValue.Black, + backgroundColor: ColorValue.Green, + }); + terminal.writeLine({ + text: msg, + foregroundColor: ColorValue.Green, + }); + }, + verbose(msg: string) { + terminal.writeVerboseLine({ + text: `${prefix} ${msg}`, + textAttributes: [TextAttribute.Dim], + }); + }, + }; +} diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/__snapshots__/addManyCustomEngine.test.ts.snap b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/__snapshots__/addManyCustomEngine.test.ts.snap new file mode 100644 index 0000000..f4303e3 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/__snapshots__/addManyCustomEngine.test.ts.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`addManyCustomEngine should add many files 1`] = ` +"/* eslint-disable */ +// prettier-ignore +import React from \\"react\\"; + +interface ImageProps { + src: string; +} + +const Image = (props: ImageProps): JSX.Element => { + const { src } = props; + return ( + + ); +}; + +export default Image; +" +`; diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/addManyCustomEngine.test.ts b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/addManyCustomEngine.test.ts new file mode 100644 index 0000000..c179f39 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/addManyCustomEngine.test.ts @@ -0,0 +1,55 @@ +import path from 'path'; +import fs from 'fs'; +import del from 'del'; +import { preparePlop } from "../utils"; + +import type { NodePlopAPI } from "node-plop"; + +describe('addManyCustomEngine', () => { + let plop: NodePlopAPI; + const baseFolder: string = path.resolve(__dirname, 'plop-templates'); + const destination: string = path.resolve(__dirname, 'output'); + const plopfilePath: string = path.resolve(__dirname, 'plopfile.js'); + beforeEach(async () => { + await del(destination); + plop = preparePlop(plopfilePath); + }); + it('should add many files', async () => { + const answer = { + packageName: 'foo' + } + plop.setGenerator("testAddManyCustomEngine", { + description: '', + prompts: [], + actions: [ + { + type: "addMany", + force: true, + destination, + base: baseFolder, + templateFiles: [`**/*`, "!init.config.ts", "!init.config.js"], + globOptions: { + cwd: baseFolder, + dot: true, + absolute: true, + }, + data: {}, + }, + ], + }); + + await plop.getGenerator("testAddManyCustomEngine").runActions(answer); + + const packageJsonFile: string = path.resolve(destination, 'pkg.json'); + expect(fs.existsSync(packageJsonFile)).toBe(true); + let packageJson = {} as any; + expect(() => { + packageJson = JSON.parse(fs.readFileSync(packageJsonFile, 'utf-8')) + }).not.toThrow(); + expect(packageJson.name).toBe('foo'); + + const indexFile: string = path.resolve(destination, 'index'); + expect(fs.existsSync(indexFile)).toBe(true); + expect(fs.readFileSync(indexFile, 'utf-8')).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/index b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/index new file mode 100644 index 0000000..07f2be9 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/index @@ -0,0 +1,20 @@ +/* eslint-disable */ +// prettier-ignore +import React from "react"; + +interface ImageProps { + src: string; +} + +const Image = (props: ImageProps): JSX.Element => { + const { src } = props; + return ( + + ); +}; + +export default Image; diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/pkg.json b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/pkg.json new file mode 100644 index 0000000..b91d390 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plop-templates/pkg.json @@ -0,0 +1,4 @@ +{ + "name": "<%= packageName %>", + "version": "1.0.0" +} diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plopfile.js b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plopfile.js new file mode 100644 index 0000000..e59ed34 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyCustomEngine/plopfile.js @@ -0,0 +1,9 @@ +/* eslint-env es6 */ +const ejs = require("ejs"); + +module.exports = function (plop) { + // A easy way to use custom render engine. + plop.renderString = function (template, data) { + return ejs.render(template, data); + }; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/addMany.test.ts b/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/addMany.test.ts new file mode 100644 index 0000000..b3d892b --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/addMany.test.ts @@ -0,0 +1,50 @@ +import path from 'path'; +import fs from 'fs'; +import del from 'del'; +import { preparePlop } from "../utils"; + +import type { NodePlopAPI } from "node-plop"; + +describe('addMany', () => { + let plop: NodePlopAPI; + const destination: string = path.resolve(__dirname, 'output'); + const baseFolder: string = path.resolve(__dirname, 'plop-templates'); + beforeEach(async () => { + await del(destination); + plop = preparePlop(); + }); + it('should add many files', async () => { + const answer = { + packageName: 'foo' + } + plop.setGenerator("testAddMany", { + description: '', + prompts: [], + actions: [ + { + type: "addMany", + force: true, + destination, + base: baseFolder, + templateFiles: [`**/*`, "!init.config.ts", "!init.config.js"], + globOptions: { + cwd: baseFolder, + dot: true, + absolute: true, + }, + data: {}, + }, + ], + }); + + await plop.getGenerator("testAddMany").runActions(answer); + + const destFile: string = path.resolve(destination, 'pkg.json'); + expect(fs.existsSync(destFile)).toBe(true); + let packageJson = {} as any; + expect(() => { + packageJson = JSON.parse(fs.readFileSync(destFile, 'utf-8')) + }).not.toThrow(); + expect(packageJson.name).toBe('foo'); + }); +}); \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/plop-templates/pkg.json b/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/plop-templates/pkg.json new file mode 100644 index 0000000..7c2c066 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/addManyRaw/plop-templates/pkg.json @@ -0,0 +1,4 @@ +{ + "name": "{{ packageName }}", + "version": "1.0.0" +} diff --git a/rush-plugins/rush-init-project-plugin/src/test/utils.ts b/rush-plugins/rush-init-project-plugin/src/test/utils.ts new file mode 100644 index 0000000..d3d8928 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/test/utils.ts @@ -0,0 +1,5 @@ +import nodePlop, { NodePlopAPI } from "node-plop"; +export const preparePlop = (plopfilePath: string = ''): NodePlopAPI => { + const plop: NodePlopAPI = nodePlop(plopfilePath, {} as any); + return plop +} \ No newline at end of file diff --git a/rush-plugins/rush-init-project-plugin/src/ui/COLORS.ts b/rush-plugins/rush-init-project-plugin/src/ui/COLORS.ts new file mode 100644 index 0000000..a7be5d9 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/COLORS.ts @@ -0,0 +1,234 @@ +export const COLORS: Record = { + black: '#000000', + red0: '#fef2ed', + red1: '#feddd2', + red2: '#fdb7a5', + red3: '#fb9078', + red4: '#fa664c', + red5: '#f93920', + red6: '#d52515', + red7: '#b2140c', + red8: '#8e0805', + red9: '#6a0103', + white: '#ffffff', + blue0: '#eaf5ff', + blue1: '#cbe7fe', + blue2: '#98cdfd', + blue3: '#65b2fc', + blue4: '#3295fb', + blue5: '#0077fa', + blue6: '#0062d6', + blue7: '#004fb3', + blue8: '#003d8f', + blue9: '#002c6b', + cyan0: '#e5f7f8', + cyan1: '#c2eff0', + cyan2: '#8adde2', + cyan3: '#58cbd3', + cyan4: '#2cb8c5', + cyan5: '#05a4b6', + cyan6: '#038698', + cyan7: '#016979', + cyan8: '#004d5b', + cyan9: '#00323d', + grey0: '#e3e3e5', + grey1: '#d0d1d3', + grey2: '#b9babd', + grey3: '#a2a3a7', + grey4: '#8a8b91', + grey5: '#73747b', + grey6: '#5c5d65', + grey7: '#45464f', + grey8: '#2d2f39', + grey9: '#161823', + lime0: '#f2fae6', + lime1: '#e3f6c5', + lime2: '#cbed8e', + lime3: '#b7e35b', + lime4: '#a7da2c', + lime5: '#9bd100', + lime6: '#7eae00', + lime7: '#638b00', + lime8: '#486800', + lime9: '#2f4600', + pink0: '#fdecef', + pink1: '#fbcfd8', + pink2: '#f6a0b5', + pink3: '#f27396', + pink4: '#ed487b', + pink5: '#e91e63', + pink6: '#c51356', + pink7: '#a20b48', + pink8: '#7e053a', + pink9: '#5a012b', + teal0: '#e4f7f4', + teal1: '#c0f0e8', + teal2: '#87e0d3', + teal3: '#54d1c1', + teal4: '#27c2b0', + teal5: '#00b3a1', + teal6: '#009589', + teal7: '#00776f', + teal8: '#005955', + teal9: '#003c3a', + amber0: '#fefbeb', + amber1: '#fcf5ce', + amber2: '#f9e89e', + amber3: '#f6d86f', + amber4: '#f3c641', + amber5: '#f0b114', + amber6: '#c88a0f', + amber7: '#a0660a', + amber8: '#784606', + amber9: '#502b03', + brand0: '#eaf5ff', + brand1: '#cbe7fe', + brand2: '#98cdfd', + brand3: '#65b2fc', + brand4: '#3295fb', + brand5: '#0077fa', + brand6: '#0062d6', + brand7: '#004fb3', + brand8: '#003d8f', + brand9: '#002c6b', + green0: '#ecf7ec', + green1: '#d0f0d1', + green2: '#a4e0a7', + green3: '#7dd182', + green4: '#5ac262', + green5: '#3bb346', + green6: '#30953b', + green7: '#25772f', + green8: '#1b5924', + green9: '#113c18', + indigo0: '#eceff8', + indigo1: '#d1d8f0', + indigo2: '#a7b3e1', + indigo3: '#8090d3', + indigo4: '#5e6fc4', + indigo5: '#3f51b5', + indigo6: '#3342a1', + indigo7: '#28348c', + indigo8: '#1f2878', + indigo9: '#171d63', + orange0: '#fff8ea', + orange1: '#feeecc', + orange2: '#fed998', + orange3: '#fdc165', + orange4: '#fda633', + orange5: '#fc8800', + orange6: '#d26700', + orange7: '#a84a00', + orange8: '#7e3100', + orange9: '#541d00', + purple0: '#f7e9f7', + purple1: '#efcaf0', + purple2: '#dd9be0', + purple3: '#c96fd1', + purple4: '#b449c2', + purple5: '#9e28b3', + purple6: '#871e9e', + purple7: '#71168a', + purple8: '#5c0f75', + purple9: '#490a61', + violet0: '#f3edf9', + violet1: '#e2d1f4', + violet2: '#c4a7e9', + violet3: '#a67fdd', + violet4: '#885bd2', + violet5: '#6a3ac7', + violet6: '#572fb3', + violet7: '#46259e', + violet8: '#361c8a', + violet9: '#281475', + yellow0: '#fffdea', + yellow1: '#fefbcb', + yellow2: '#fdf398', + yellow3: '#fce865', + yellow4: '#fbda32', + yellow5: '#fac800', + yellow6: '#d0aa00', + yellow7: '#a78b00', + yellow8: '#7d6a00', + yellow9: '#534800', + tiktokbg0: '#ffffff', + tiktokbg1: '#f8f8f8', + tiktokbg2: '#f5f5f5', + tiktokbg3: '#f1f1f1', + tiktokbg4: '#e8e8e9', + tiktokbg5: '#d9d9d9', + tiktokbg6: '#cccccc', + tiktokbg7: '#a3a3a3', + tiktokbg8: '#7b7b7b', + tiktokbg9: '#525252', + lightblue0: '#e9f7fd', + lightblue1: '#c9ecfc', + lightblue2: '#95d8f8', + lightblue3: '#62c3f5', + lightblue4: '#30acf1', + lightblue5: '#0095ee', + lightblue6: '#007bca', + lightblue7: '#0063a7', + lightblue8: '#004b83', + lightblue9: '#00355f', + tiktokred0: '#ffeff0', + tiktokred1: '#ffd5d7', + tiktokred2: '#ffaab2', + tiktokred3: '#fe8090', + tiktokred4: '#fe5671', + tiktokred5: '#fe2c55', + tiktokred6: '#da1f4a', + tiktokred7: '#b7153f', + tiktokred8: '#930c34', + tiktokred9: '#6f0629', + lightgreen0: '#f3f8ec', + lightgreen1: '#e3f0d0', + lightgreen2: '#c8e2a5', + lightgreen3: '#add37e', + lightgreen4: '#93c55b', + lightgreen5: '#7bb63c', + lightgreen6: '#649830', + lightgreen7: '#4e7926', + lightgreen8: '#395b1b', + lightgreen9: '#253d12', + tiktokblue0: '#ecfcfd', + tiktokblue1: '#d0f9fb', + tiktokblue2: '#a2f2f7', + tiktokblue3: '#75eaf4', + tiktokblue4: '#4ae0f0', + tiktokblue5: '#20d5ec', + tiktokblue6: '#19aec5', + tiktokblue7: '#12899d', + tiktokblue8: '#0c6576', + tiktokblue9: '#08424f', + tiktokblack0: '#e5e6e9', + tiktokblack1: '#c3c7d3', + tiktokblack2: '#b0b0b4', + tiktokblack3: '#73747b', + tiktokblack4: '#50525a', + tiktokblack5: '#161823', + tiktokblack6: '#090a0f', + tiktokblack7: '#000000', + tiktokblack8: '#000000', + tiktokblack9: '#000000', + tiktokgreen0: '#e9fcf4', + tiktokgreen1: '#c9f9e6', + tiktokgreen2: '#96f3d0', + tiktokgreen3: '#66ecbc', + tiktokgreen4: '#37e6ab', + tiktokgreen5: '#0be09b', + tiktokgreen6: '#07bb84', + tiktokgreen7: '#04956b', + tiktokgreen8: '#027052', + tiktokgreen9: '#014b38', + tiktokorange0: '#fff4f0', + tiktokorange1: '#ffe0d8', + tiktokorange2: '#ffbfb0', + tiktokorange3: '#ff9b89', + tiktokorange4: '#ff7561', + tiktokorange5: '#ff4c3a', + tiktokorange6: '#db362b', + tiktokorange7: '#b8231f', + tiktokorange8: '#941415', + tiktokorange9: '#700c10' +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/EMIT_EVENTS.ts b/rush-plugins/rush-init-project-plugin/src/ui/EMIT_EVENTS.ts new file mode 100644 index 0000000..23c0a51 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/EMIT_EVENTS.ts @@ -0,0 +1,9 @@ +/** + * This file is used to record custom events. + * Do not name events direct in the system. + * Because you might register others's action. + */ +export const CUSTOM_EMIT_EVENTS: Record = { + SUBMIT_ANSWERS: 'submit answers', + UPDATE_LAYOUT: 'update layout' +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/EventManager.ts b/rush-plugins/rush-init-project-plugin/src/ui/EventManager.ts new file mode 100644 index 0000000..906ede9 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/EventManager.ts @@ -0,0 +1,49 @@ +export const PROCESS_STATUS: Record = { + NULL: -1, + START: 0, + TEMPLATE_SELECTING: 1, + FORM_FILLING: 2, + ACTIONS_INVOKING: 3, + FINISHED: 4 +}; + +let currentState: number = PROCESS_STATUS.NULL; + +export const getCurrentState = (): number => { + return currentState; +}; +export const start = (): void => { + currentState = PROCESS_STATUS.TEMPLATE_SELECTING; +}; +export const goNext = (): void => { + switch (currentState) { + case PROCESS_STATUS.NULL: + currentState = PROCESS_STATUS.START; + break; + case PROCESS_STATUS.START: + currentState = PROCESS_STATUS.TEMPLATE_SELECTING; + break; + case PROCESS_STATUS.TEMPLATE_SELECTING: + currentState = PROCESS_STATUS.FORM_FILLING; + break; + case PROCESS_STATUS.FORM_FILLING: + currentState = PROCESS_STATUS.ACTIONS_INVOKING; + break; + case PROCESS_STATUS.ACTIONS_INVOKING: + currentState = PROCESS_STATUS.FINISHED; + break; + default: + currentState = PROCESS_STATUS.NULL; + break; + } +}; + +// const goPrev = () => { +// switch(currentState){ +// case PROCESS_STATUS.FORM_FILLING: +// currentState = PROCESS_STATUS.TEMPLATE_SELECTING; +// break; +// default +// break; +// } +// } diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/AutoCompleteComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/AutoCompleteComponent.ts new file mode 100644 index 0000000..98379d1 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/AutoCompleteComponent.ts @@ -0,0 +1,271 @@ +import { BaseFieldComponent, IComponentOptions, IExtendedAnswers } from './BaseFieldComponent'; +import blessed, { Widgets, list } from 'blessed'; + +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import AutocompletePrompt from 'inquirer-autocomplete-prompt'; +import { nextTick } from 'process'; +import { COLORS } from '../COLORS'; +import { BlessedHiddenInputComponent } from './BlessedHiddenInputComponent'; +import { ListComponent } from './ListComponent'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +const SELECT_TEXT_LABEL: string = `{${COLORS.grey0}}search in the list, select by space/enter{/${COLORS.grey0}}`; + +interface IPromiseState { + state: boolean; + value: string; +} + +export class AutoCompleteComponent extends BaseFieldComponent { + public placeholder: Widgets.BoxElement; + public input: Widgets.TextareaElement; + public hiddenInput: BlessedHiddenInputComponent; + public sourceList: Widgets.ListElement; + private _messageState: IPromiseState = { + state: false, + value: '' + }; + private _defaultState: IPromiseState = { + state: false, + value: '' + }; + private _inputCache: string; + private _choices: Array = []; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + super(form, prompt, option, hookForPrompt); + // listener on prompt + const _: AutoCompleteComponent = this; + this.prompt = new Proxy(prompt, { + set(target: Record void>, prop: string, newValue: string | (() => void)) { + switch (prop) { + case 'default': + // eslint-disable-next-line no-void + void _.setDefaultValue(); + break; + default: + break; + } + return true; + } + }); + + this.input = blessed.textarea({ + name: `_autocomplete_${prompt.name}`, + parent: this.form, + inputOnFocus: true, + border: 'line', + width: '100%', + height: 3, + style: { + focus: { + border: { + fg: COLORS.green5 + } + } + }, + alwaysScroll: true, + scrollable: false, + shrink: true + }); + this._inputCache = this.input.getValue(); + this.hiddenInput = new BlessedHiddenInputComponent({ + name: prompt.name, + parent: this.form, + hidden: true + }); + this.sourceList = this.createList(); + this.placeholder = blessed.box({ + tags: true, + parent: this.form, + height: 1, + alwaysScroll: true, + shrink: true, + width: '100%' + }); + this.input.on('focus', () => { + this.label.style.fg = COLORS.green5; + const scrollTop: number = Number(this.label.top) ?? 0; + if (scrollTop) { + form.scrollTo(scrollTop); + } + this.form.screen.render(); + }); + this.input.on('blur', async () => { + this.label.style.fg = COLORS.black; + this._inputCache = this.input.getValue(); + this.form.screen.render(); + }); + this.input.key(['return'], () => { + // Workaround, since we can't stop the return from being added. + this.input.emit('keypress', null, { name: 'backspace' }); + this.input.emit('keypress', '\x1b', { name: 'escape' }); + this.form.focusNext(); + return; + }); + this.input.on('keypress', () => { + // to get on time input + nextTick(async () => { + if (this._inputCache !== this.input.value) { + await this.setItems(this.input.value); + this.sourceList.emit('select', this.sourceList.getItem(0), 0); + } + }); + }); + this.elements.push(this.label, this.input, this.sourceList, this.placeholder); + } + public createList(): Widgets.ListElement { + const sourceList: Widgets.ListElement = list({ + name: `_list_${this.prompt.name}`, + parent: this.form, + keys: true, + width: '100%', + height: 5, + border: 'line', + content: 'empty', + scrollable: true, + alwaysScroll: true, + scrollbar: { + ch: ' ', + track: { + bg: COLORS.grey0 + }, + style: { + inverse: true + } + }, + style: { + selected: { + bg: COLORS.grey0 + }, + focus: { + border: { + fg: COLORS.green5 + } + } + } + } as Widgets.ListOptions); + + let currentSelectedItem: Widgets.BoxElement; + let currentSelectedItemStyle: Record = {}; + + sourceList.on('focus', () => { + this.label.style.fg = COLORS.green5; + this.form.screen.render(); + }); + sourceList.on('blur', async () => { + this.label.style.fg = COLORS.black; + await this.validateResult(); + this.form.screen.render(); + }); + + sourceList.on('select', (el: Widgets.BoxElement, selected: number) => { + if (sourceList._.rendering) return; + this.hiddenInput.setValue(this._choices[selected]); + // set selected item different color + // @ts-ignore + currentSelectedItem?.style = currentSelectedItemStyle; + currentSelectedItem = el; + currentSelectedItemStyle = el?.style; + // @ts-ignore + currentSelectedItem?.style = { + bg: COLORS.red4 + }; + this.label.setContent(this._messageState.value); + this.form.screen.render(); + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT); + }); + // store current select index, + let currentSelectedItemIndex: number = 0; + sourceList.on('select item', (el: Widgets.BoxElement, selected: number) => { + nextTick(() => { + currentSelectedItemIndex = selected; + }); + }); + + sourceList.key(['space'], () => { + sourceList.emit('keypress', '\r', { name: 'enter' }); + }); + const removeKeys = (el: ListComponent, ch: string, key: Widgets.Events.IKeyEventArg): boolean => { + if (key.name === 'up' && currentSelectedItemIndex === 0) { + return true; + } + if (key.name === 'down' && currentSelectedItemIndex === this._choices.length - 1) { + return true; + } + if (key.name === 'up' || key.name === 'down') { + return false; + } + return true; + }; + sourceList.on('element keypress', removeKeys); + return sourceList; + } + public async validateResult(): Promise { + this.isValidate = await this.validate({ value: this.hiddenInput.getValue() }); + if (this.isValidate === true) { + this.label.setContent(this._messageState.value); + this.placeholder.setContent(''); + } else { + const warningStr: string = this.isValidate ? this.isValidate : 'error'; + this.label.setContent(`{${COLORS.red6}-fg}*{/${COLORS.red6}-fg}${this._messageState.value}`); + this.placeholder.setContent(`{${COLORS.red6}-fg}[${warningStr}]{/${COLORS.red6}-fg}`); + } + } + public async setMessage(): Promise { + if (this._messageState.state) { + return; + } + this._messageState.state = true; + try { + const message: string = await this.message(); + this._messageState.value = `${message}${SELECT_TEXT_LABEL}`; + this.label.setContent(`${this._messageState.value}`); + } catch (e) { + this.form.screen.log('autocomplete set message error', e); + } + this._messageState.state = false; + } + public async setDefaultValue(): Promise { + if (this._defaultState.state) { + return; + } + this._defaultState.state = true; + try { + if (this.input.getValue()) { + return; + } + const defaultValue: string = (await this.default()) as string; + if (defaultValue === this._defaultState.value) { + this._defaultState.state = false; + return; + } + await this.setItems(); + this._defaultState.value = defaultValue; + const tempIndex: number = this._choices.indexOf(defaultValue); + const selectedIndex: number = tempIndex >= 0 ? tempIndex : 0; + this.sourceList.emit('select', this.sourceList.getItem(selectedIndex), selectedIndex); + } catch (e) { + this.form.screen.log('autocomplete set default error', e); + } + this._defaultState.state = false; + } + public async setItems(value?: string): Promise { + this.form.submit(); + const prompt: AutocompletePrompt.AutocompleteQuestionOptions = this + .prompt as AutocompletePrompt.AutocompleteQuestionOptions; + const items: string[] = await prompt.source(this.form.submission, value); + this.sourceList.clearItems(); + this._choices = items; + items.forEach((str: string) => { + this.sourceList.add(str); + }); + this.form.screen.render(); + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/BaseFieldComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/BaseFieldComponent.ts new file mode 100644 index 0000000..1cbf6b4 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/BaseFieldComponent.ts @@ -0,0 +1,251 @@ +import { box, Widgets } from 'blessed'; +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; + +export interface IComponentOptions { + height: number; + top: number; +} +export type BaseValueType = number | string | boolean | Array; +export interface IExtendedAnswers extends Answers { + authorName: string; + description: string; + template: string; + packageName: string; + unscopedPackageName: string; + projectFolder: string; + shouldRunRushUpdate: boolean; +} + +/** + * This is a basic Field component based on inquirer + * Any new component based on inquirer should extend this class + */ +export class BaseFieldComponent { + /** + * Each Field need a label + */ + public label: Widgets.BoxElement; + public option: IComponentOptions; + public form: Widgets.FormElement; + public prompt: PromptQuestion; + /** + * control the active of the this field, if this field is active, its value is active and it's visible + */ + public isActived: boolean = true; + /** + * validation of the field + */ + public isValidate: boolean | string = true; + /** + * all elements involved in field + */ + public elements: Array = []; + private _hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + this.form = form; + this.prompt = prompt; + this.option = option; + this._hookForPrompt = hookForPrompt; + this.label = box({ + tags: true, + parent: this.form, + height: 1, + content: this.prompt.name, + alwaysScroll: true, + shrink: true + }); + } + /** + * validate result based on blessed widget implemented by every component + */ + public async validateResult(): Promise {} + /** + * set default value on the blessed widget implemented by every component + */ + public async setDefaultValue(): Promise {} + /** + * set content on the blessed widget implemented by every component + */ + public async setMessage(): Promise {} + /** + * used for blessed to focus on field implemented by every component + */ + public focus(): void {} + /** + * used for blessed to focus on next field + */ + public focusNext(): void { + this.form.focusNext(); + } + /** + * get really field object + */ + public getFieldComponent(): Widgets.Node | undefined { + return; + } + public reset(): void {} + public render(): void { + this.form.screen.render(); + } + public async invokeHooks(): Promise { + if (this._hookForPrompt) { + await this._hookForPrompt.call(this.prompt, this.form.submission); + } + } + /** + * get current total height of all elements and it's top + */ + public getLayout(): IComponentOptions { + return this.elements.reduce( + (prev, cur) => { + let height: number = 0; + if (this.isActived) { + if (cur instanceof Array) { + height = Number(cur[0]?.height ?? 0); + } else { + height = Number(cur?.height ?? 0); + } + } + return { + height: Number(prev.height) + height, + top: prev.top + }; + }, + { height: 0, top: this.option.top } + ); + } + /** + * update and top of all elements + */ + public updateLayout(updateOption: IComponentOptions): IComponentOptions { + this.option = { ...this.option, ...updateOption }; + const top: number = Number(this.option.top) ?? 0; + let totalHeight: number = 0; + this.elements.forEach((ele: Widgets.BoxElement | Widgets.BoxElement[], index: number) => { + if (ele instanceof Array) { + ele.forEach((item: Widgets.BoxElement) => { + item.top = top + totalHeight; + }); + if (this.isActived) { + totalHeight += Number(ele[0]?.height ?? 0); + } + } else { + ele.top = top + totalHeight; + if (this.isActived) { + totalHeight += Number(ele?.height ?? 0); + } + } + }); + return { + top, + height: totalHeight + }; + } + /** + * The default value of the question. + * implement of default param in inquirer + */ + public async default(): Promise { + let defaultValue: BaseValueType = ''; + switch (typeof this.prompt.default) { + case 'function': + defaultValue = (await this.prompt.default(this.form.submission)) ?? ''; + break; + case 'boolean': + defaultValue = this.prompt.default; + break; + case 'number': + defaultValue = this.prompt.default; + break; + default: + defaultValue = this.prompt.default ?? ''; + break; + } + return defaultValue; + } + /** + * The message value of the question. + * implement of message param in inquirer + */ + public async message(): Promise { + let message: string = ''; + if (typeof this.prompt.message === 'function') { + message = (await this.prompt.message(this.form.submission)) ?? ''; + } else if (typeof this.prompt.message === 'string') { + message = this.prompt.message ?? ''; + } + return message; + } + /** + * Validates the integrity of the answer. + * implement of validate param in inquirer + * + * @param input + * The answer provided by the user. + * + * @returns + * If this field is inactive, it will always return true + * Either a value indicating whether the answer is valid or a `string` which describes the error. + */ + public async validate(value: BaseValueType | { value: BaseValueType }): Promise { + if (!this.isActived) { + return true; + } + const { validate } = this.prompt; + if (typeof validate === 'function') { + this.form.submit(); + return await validate(value, this.form.submission); + } + return true; + } + /** + * A value indicating whether the question should be prompted. + * implement of when param in inquirer + */ + public async when(): Promise { + let currentActive: boolean = true; + switch (typeof this.prompt.when) { + case 'function': + currentActive = await this.prompt.when(this.form.submission); + break; + default: + currentActive = true; + break; + } + if (this.isActived === currentActive) { + return; + } + this.isActived = currentActive; + this.elements.forEach((ele: Widgets.BoxElement | Widgets.BoxElement[], index: number) => { + if (ele instanceof Array) { + ele.forEach((item: Widgets.BoxElement) => { + if (this.isActived) { + item.show(); + } else { + item.hide(); + } + }); + } else { + if (this.isActived) { + ele.show(); + } else { + ele.hide(); + } + } + }); + } + /** + * init state include default and message config + */ + public async initState(): Promise { + await this.setMessage(); + await this.setDefaultValue(); + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/BlessedHiddenInputComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/BlessedHiddenInputComponent.ts new file mode 100644 index 0000000..7652493 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/BlessedHiddenInputComponent.ts @@ -0,0 +1,21 @@ +import { Widgets } from 'blessed'; +import { BaseValueType } from './BaseFieldComponent'; +import Box from 'blessed/lib/widgets/box'; + +export class BlessedHiddenInputComponent extends Box { + public value: BaseValueType; + public type: string = 'hiddeninput'; + public constructor(opts: Widgets.InputOptions) { + super(opts); + this.value = ''; + } + public setValue(value: BaseValueType): void { + if (!value) { + return; + } + this.value = value; + } + public getValue(): BaseValueType { + return this.value; + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/CheckboxComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/CheckboxComponent.ts new file mode 100644 index 0000000..1308975 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/CheckboxComponent.ts @@ -0,0 +1,126 @@ +import { BaseFieldComponent, IComponentOptions, IExtendedAnswers, BaseValueType } from './BaseFieldComponent'; +import blessed, { Widgets } from 'blessed'; + +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import { COLORS } from '../COLORS'; +import { BlessedHiddenInputComponent } from './BlessedHiddenInputComponent'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +export class CheckboxComponent extends BaseFieldComponent { + public placeholder: Widgets.BoxElement; + public checkboxes: Array = []; + private _checkboxesFieldName: string; + public hiddenInput: BlessedHiddenInputComponent; + private _message: string = ''; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + super(form, prompt, option, hookForPrompt); + let left: number = 0; + this._checkboxesFieldName = `_${this.prompt.name}_checkbox`; + const choices: Array = (this.prompt as Record)?.choices as Array; + const isHorizontal: boolean = choices.length <= 3; + choices?.forEach((element: string, index: number) => { + const CheckBox: Widgets.CheckboxElement = blessed.checkbox({ + parent: this.form, + text: element, + name: this._checkboxesFieldName, + checked: false, + width: element.length + 4, + left, + height: 1, + shrink: true, + alwaysScroll: true, + style: { + focus: { + fg: COLORS.green5 + } + } + }); + if (isHorizontal) { + left += element.length + 5; + } + CheckBox.on('check', () => { + this.setValue(); + }); + CheckBox.on('uncheck', () => { + this.setValue(); + }); + CheckBox.on('focus', () => { + this.label.style.fg = COLORS.green5; + this.form.screen.render(); + }); + CheckBox.on('blur', async () => { + this.label.style.fg = COLORS.black; + await this.validateResult(); + }); + this.checkboxes.push(CheckBox); + }); + this.hiddenInput = new BlessedHiddenInputComponent({ + hidden: true, + parent: this.form, + name: this.prompt.name + }); + this.placeholder = blessed.box({ + tags: true, + parent: this.form, + height: 1, + alwaysScroll: true, + shrink: true, + width: '100%' + }); + if (isHorizontal) { + this.elements.push(this.label, this.checkboxes, this.placeholder); + } else { + this.elements.push(this.label, ...this.checkboxes, this.placeholder); + } + } + public async validateResult(): Promise { + if (this.prompt.name) { + this.isValidate = await this.validate(this.hiddenInput.getValue()); + if (this.isValidate === true) { + this.label.setContent(`${this._message}`); + this.placeholder.setContent(''); + } else { + const warningStr: string = this.isValidate ? this.isValidate : 'error'; + this.label.setContent(`{${COLORS.red6}-fg}*{/${COLORS.red6}-fg}${this._message}`); + this.placeholder.setContent(`{${COLORS.red6}-fg}[${warningStr}]{/${COLORS.red6}-fg}`); + } + } + this.form.screen.render(); + } + public setValue(): void { + const res: BaseValueType = + this.checkboxes.filter((checkbox) => checkbox.checked)?.map((checkbox) => checkbox.text) ?? []; + this.hiddenInput.setValue(res); + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT); + } + public async setMessage(): Promise { + try { + const message: string = await this.message(); + this._message = message; + this.label.setContent(message); + } catch (e) { + this.form.screen.log('checkbox set message error', e); + } + } + public async setDefaultValue(): Promise { + try { + const defaultValue: string = (await this.default()) as string; + const values: Array = (defaultValue as unknown as Array) ?? []; + this.checkboxes.forEach((checkbox) => { + if (values?.indexOf(checkbox.text) >= 0) { + checkbox.check(); + } + }); + this.setValue(); + } catch (e) { + this.form.screen.log('checkbox set default error', e); + } + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/ConfirmComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/ConfirmComponent.ts new file mode 100644 index 0000000..9781c83 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/ConfirmComponent.ts @@ -0,0 +1,87 @@ +import { BaseFieldComponent, BaseValueType, IComponentOptions, IExtendedAnswers } from './BaseFieldComponent'; +import blessed, { Widgets } from 'blessed'; + +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import { COLORS } from '../COLORS'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +export class ConfirmComponent extends BaseFieldComponent { + public placeholder: Widgets.BoxElement; + public confimBtn: Widgets.CheckboxElement; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + super(form, prompt, option, hookForPrompt); + this.confimBtn = blessed.checkbox({ + parent: this.form, + height: 1, + name: this.prompt.name, + text: 'yes', + alwaysScroll: true, + shrink: true, + style: { + focus: { + fg: COLORS.green5 + } + } + }); + + this.confimBtn.on('check', () => { + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT, { [this.confimBtn.name]: this.confimBtn.checked }); + }); + this.confimBtn.on('uncheck', () => { + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT, { [this.confimBtn.name]: this.confimBtn.checked }); + }); + this.confimBtn.on('focus', () => { + this.label.style.fg = COLORS.green5; + this.form.screen.render(); + }); + this.confimBtn.on('blur', async () => { + this.label.style.fg = COLORS.black; + this.form.screen.render(); + }); + + // hidden confirm will affect other components + this.confimBtn.on('show', async () => { + await this.setDefaultValue(); + }); + this.confimBtn.on('hide', () => { + if (this.confimBtn.checked) { + this.confimBtn.uncheck(); + } + }); + + this.placeholder = blessed.box({ + parent: this.form, + height: 1, + alwaysScroll: true, + shrink: true, + width: '100%' + }); + this.elements.push(this.label, this.confimBtn, this.placeholder); + } + public async setMessage(): Promise { + try { + const message: string = await this.message(); + this.label.setContent(message); + } catch (e) { + this.form.screen.log('confirm set message error', e); + } + } + public async setDefaultValue(): Promise { + try { + const defaultValue: BaseValueType = await this.default(); + if (defaultValue === false) { + return; + } + this.confimBtn.check(); + } catch (e) { + this.form.screen.log('confirm set default error', e); + } + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/InputComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/InputComponent.ts new file mode 100644 index 0000000..334e6ce --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/InputComponent.ts @@ -0,0 +1,108 @@ +import { BaseFieldComponent, IComponentOptions, IExtendedAnswers } from './BaseFieldComponent'; +import blessed, { Widgets } from 'blessed'; + +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import { COLORS } from '../COLORS'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +export class InputComponent extends BaseFieldComponent { + public input: Widgets.TextareaElement; + public placeholder: Widgets.BoxElement; + private _message: string = ''; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + super(form, prompt, option, hookForPrompt); + this.input = blessed.textarea({ + name: this.prompt.name, + parent: this.form, + inputOnFocus: true, + width: '100%', + height: 3, + border: 'line', + scrollable: false, + style: { + focus: { + border: { + fg: COLORS.green5 + } + } + }, + alwaysScroll: true, + shrink: true + }); + this.input.key(['return'], () => { + // Workaround, since we can't stop the return from being added. + this.input.emit('keypress', null, { name: 'backspace' }); + this.input.emit('keypress', '\x1b', { name: 'escape' }); + this.focusNext(); + return; + }); + this.input.on('focus', () => { + this.label.style.fg = COLORS.green5; + this.form.screen.render(); + }); + this.input.on('blur', async () => { + this.label.style.fg = COLORS.black; + await this.validateResult(); + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT); + }); + this.placeholder = blessed.box({ + tags: true, + parent: this.form, + height: 1, + alwaysScroll: true, + shrink: true, + width: '100%' + }); + this.elements.push(this.label, this.input, this.placeholder); + } + public focus(): void { + this.input.focus(); + } + public async validateResult(): Promise { + this.label.setContent(`${this._message} {${COLORS.blue4}-fg}[validating...]{/${COLORS.blue4}-fg}`); + try { + this.isValidate = await this.validate(this.input.getValue()); + } catch (error) { + this.isValidate = ((error ?? 'error') as string).toString(); + } + if (this.isValidate === true) { + this.label.setContent(`${this._message}`); + this.placeholder.setContent(''); + } else { + const warningStr: string = this.isValidate ? this.isValidate : 'error'; + this.label.setContent(`{${COLORS.red6}-fg}*{/${COLORS.red6}-fg}${this._message}`); + this.placeholder.setContent(` {${COLORS.red6}-fg}[${warningStr}]{/${COLORS.red6}-fg}`); + } + this.form.screen.render(); + } + + public async setMessage(): Promise { + try { + const message: string = await this.message(); + this._message = message; + this.label.setContent(this._message); + } catch (e) { + this.form.screen.log('input set message error', e); + } + } + public async setDefaultValue(): Promise { + try { + const defaultValue: string = (await this.default()) as string; + if (defaultValue) { + this.input.value = defaultValue; + } + } catch (e) { + this.form.screen.log('input set default error', e); + } + } + public getFieldComponent(): Widgets.Node { + return this.input; + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/ListComponent.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/ListComponent.ts new file mode 100644 index 0000000..7546ceb --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/ListComponent.ts @@ -0,0 +1,177 @@ +import { BaseFieldComponent, IComponentOptions, IExtendedAnswers } from './BaseFieldComponent'; +import blessed, { Widgets, list } from 'blessed'; + +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import { COLORS } from '../COLORS'; +import { BlessedHiddenInputComponent } from './BlessedHiddenInputComponent'; +import { nextTick } from 'process'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +export class ListComponent extends BaseFieldComponent { + public placeholder: Widgets.BoxElement; + public hiddenInput: BlessedHiddenInputComponent; + public sourceList: Widgets.ListElement; + private _message: string = ''; + public choices: Array = []; + private _ListFieldName: string = ''; + public constructor( + form: Widgets.FormElement, + prompt: PromptQuestion, + option: IComponentOptions, + hookForPrompt: SyncHook<[PromptQuestion, Partial], null | undefined> | undefined + ) { + super(form, prompt, option, hookForPrompt); + this._ListFieldName = `_list_field_name`; + this.sourceList = this.createList(); + this.placeholder = blessed.box({ + tags: true, + parent: this.form, + height: 1, + alwaysScroll: true, + shrink: true, + width: '100%' + }); + this.hiddenInput = new BlessedHiddenInputComponent({ + name: prompt.name, + parent: this.form, + hidden: true, + value: [] + }); + this.elements.push(this.label, this.sourceList, this.placeholder); + } + public createList(): Widgets.ListElement { + const sourceList: Widgets.ListElement = list({ + parent: this.form, + name: this._ListFieldName, + keys: true, + width: '100%', + height: 5, + border: 'line', + scrollable: true, + parseTags: true, + alwaysScroll: true, + scrollbar: { + ch: ' ', + track: { + bg: COLORS.grey0 + }, + style: { + inverse: true + } + }, + style: { + selected: { + bg: COLORS.grey0 + }, + focus: { + border: { + fg: COLORS.green5 + } + } + } + } as Widgets.ListOptions); + + let currentSelectedItem: Widgets.BoxElement; + let currentSelectedItemStyle: Record; + sourceList.on('select', (el: Widgets.BoxElement, selected: number) => { + if (sourceList._.rendering) return; + const text: string = this.choices[selected]; + this.hiddenInput.setValue(text); + + // set selected item different color + // @ts-ignore + currentSelectedItem?.style = currentSelectedItemStyle; + currentSelectedItem = el; + currentSelectedItemStyle = el?.style; + // @ts-ignore + currentSelectedItem?.style = { + bg: COLORS.red4 + }; + this.label.setContent(`${this._message}`); + this.form.screen.render(); + this.form.emit(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT); + }); + sourceList.on('focus', () => { + this.label.style.fg = COLORS.green5; + }); + sourceList.on('blur', async () => { + this.label.style.fg = COLORS.black; + await this.validateResult(); + }); + // store current select index, + let currentMoveItemIndex: number = 0; + sourceList.on('select item', (el: Widgets.BoxElement, selected: number) => { + nextTick(() => { + currentMoveItemIndex = selected; + }); + }); + // prevent default form keys, if it's first or last one, run default function + const removeKeys = (el: ListComponent, ch: string, key: Widgets.Events.IKeyEventArg): boolean => { + if (key.name === 'up' && currentMoveItemIndex === 0) { + return true; + } + if (key.name === 'down' && currentMoveItemIndex === this.choices.length - 1) { + return true; + } + if (key.name === 'up' || key.name === 'down') { + return false; + } + return true; + }; + sourceList.on('element keypress', removeKeys); + sourceList.key(['space'], () => { + sourceList.emit('keypress', '\r', { name: 'enter' }); + }); + return sourceList; + } + public async validateResult(): Promise { + this.isValidate = await this.validate(this.hiddenInput.getValue()); + if (this.isValidate === true) { + this.label.setContent(`${this._message}`); + this.placeholder.setContent(''); + } else { + const warningStr: string = this.isValidate ? this.isValidate : 'error'; + this.label.setContent(`{${COLORS.red6}-fg}*{/${COLORS.red6}-fg}${this._message}`); + this.placeholder.setContent(`{${COLORS.red6}-fg}[${warningStr}]{/${COLORS.red6}-fg}`); + } + } + public async setMessage(): Promise { + try { + const message: string = await this.message(); + this._message = message; + this.label.setContent(message); + } catch (e) { + this.form.screen.log('list set message error', e); + } + } + public async setDefaultValue(): Promise { + try { + const defaultValue: string = (await this.default()) as string; + await this.setItems(); + const tempIndex: number = this.choices.indexOf(defaultValue); + const selectedIndex: number = tempIndex >= 0 ? tempIndex : 0; + this.sourceList.emit('select', this.sourceList.getItem(selectedIndex), selectedIndex); + } catch (e) { + this.form.screen.log('list set default error', e); + } + } + public async setItems(): Promise { + this.form.submit(); + const choicesRaw: Array | ((answers: Answers) => Array) = ( + this.prompt as Record + )?.choices as Array | Array | ((answers: Answers) => Array); + let items: string[] = []; + if (typeof choicesRaw === 'function') { + items = await choicesRaw(this.form.submission); + } else if (choicesRaw instanceof Array) { + items = choicesRaw; + } + this.choices = items; + this.choices.forEach((str: string) => { + this.sourceList.add(str); + }); + this.form.screen.render(); + } +} diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/Warning.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/Warning.ts new file mode 100644 index 0000000..e1f0f9b --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/Warning.ts @@ -0,0 +1,22 @@ +import { box, Widgets } from 'blessed'; +import { COLORS } from '../COLORS'; + +export const Warning = (): { + WarningBox: Widgets.BoxElement; + setWarningContent: (content: string) => void; +} => { + const WarningBox: Widgets.BoxElement = box({ + bottom: 0, + height: 1, + transparent: true, + index: 10, + style: { + fg: COLORS.amber6 + } + }); + const setWarningContent = (content: string): void => { + WarningBox.setContent(content); + }; + // list.focus(); + return { WarningBox, setWarningContent }; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/form.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/form.ts new file mode 100644 index 0000000..15214da --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/form.ts @@ -0,0 +1,248 @@ +import blessed, { Widgets } from 'blessed'; +import { InputComponent } from './InputComponent'; +import { ConfirmComponent } from './ConfirmComponent'; +import { CheckboxComponent } from './CheckboxComponent'; +import { AutoCompleteComponent } from './AutoCompleteComponent'; +import type { PromptQuestion } from 'node-plop'; +import type { SyncHook } from 'tapable'; +import { Answers } from 'inquirer'; +import { IHooks, getHooks } from '../../hooks'; +import { IComponentOptions, IExtendedAnswers } from './BaseFieldComponent'; +import { ListComponent } from './ListComponent'; +import { COLORS } from '../COLORS'; +import { CUSTOM_EMIT_EVENTS } from '../EMIT_EVENTS'; + +type FieldComponent = + | InputComponent + | ConfirmComponent + | CheckboxComponent + | AutoCompleteComponent + | ListComponent; + +const DEFAULT_TEXT: string = '{center}{bold}SUBMIT{bold}{/center}'; +const SUBMINTING_TEXT: string = '{center}submiting, please wait patiently{/center}'; + +const createSubmit = ( + form: Widgets.FormElement, + formValidateAndSubmit: () => {} +): Widgets.ButtonElement => { + const submitBtn: Widgets.ButtonElement = blessed.button({ + parent: form, + name: '_submit', + tags: true, + height: 3, + border: 'line', + content: DEFAULT_TEXT, + style: { + fg: COLORS.blue2, + border: { + fg: COLORS.blue2 + }, + hover: { + fg: COLORS.blue4, + border: { + fg: COLORS.blue4 + } + }, + focus: { + fg: COLORS.green5, + border: { + fg: COLORS.green5 + } + } + } + }); + let isSubmitting: boolean = false; + const submitAnswer = async (): Promise => { + if (isSubmitting) { + return; + } + submitBtn.setContent(SUBMINTING_TEXT); + submitBtn.screen.render(); + isSubmitting = !isSubmitting; + try { + const res: Answers | boolean = await formValidateAndSubmit(); + if (res) { + form.emit(CUSTOM_EMIT_EVENTS.SUBMIT_ANSWERS, res); + } + } catch (e) { + form.screen.log('form submit error', e); + } + submitBtn.setContent(DEFAULT_TEXT); + submitBtn.screen.render(); + isSubmitting = !isSubmitting; + }; + submitBtn.on( + 'element keypress', + (el: ListComponent, ch: string, key: Widgets.Events.IKeyEventArg): boolean => { + if (key.name === 'down') { + return false; + } + return true; + } + ); + submitBtn.on( + 'element keypress', + async (el: ListComponent, ch: string, key: Widgets.Events.IKeyEventArg): Promise => { + if (key.name === 'return' || key.name === 'space') { + await submitAnswer(); + } + return true; + } + ); + submitBtn.on('click', async () => { + submitBtn.emit('keypress', '\r', { name: 'enter' }); + }); + return submitBtn; +}; + +const createValidateMessage = (screen: Widgets.Screen): Widgets.MessageElement => { + // elements + const message: Widgets.MessageElement = blessed.message({ + parent: screen, + border: 'line', + height: 'shrink', + width: 'shrink', + top: 'center', + left: 'center', + index: 100, + label: ' {blue-fg}Validate Error{/blue-fg} ', + tags: true, + keys: true, + hidden: true + }); + return message; +}; + +export const Form = async ( + promptQueue: Array +): Promise<{ + form: Widgets.FormElement; +}> => { + const hooks: IHooks = getHooks(); + const form: Widgets.FormElement = blessed.form({ + keys: true, + shrink: true, + height: '100%-2', + width: '100%', + top: 2, + scrollable: true, + alwaysScroll: true + }) as Widgets.FormElement; + + // process promte fields and append to form + const promoteField: Array = []; + for (let i: number = 0; i < promptQueue.length; i++) { + let prompt: PromptQuestion = promptQueue[i]; + let fieldRender: FieldComponent; + + const option: IComponentOptions = { + top: 4 * i, + height: 0 + }; + const hookForCurrentPrompt: + | SyncHook<[PromptQuestion, Partial], null | undefined> + | undefined = hooks.promptQuestion.get(prompt.name); + + if (hookForCurrentPrompt) { + form.submit(); + await hookForCurrentPrompt.call(prompt, form.submission); + prompt = promptQueue[i]; + } + + switch (prompt.type) { + case 'confirm': + fieldRender = new ConfirmComponent(form, prompt, option, hookForCurrentPrompt); + break; + case 'checkbox': + fieldRender = new CheckboxComponent(form, prompt, option, hookForCurrentPrompt); + break; + case 'list': + fieldRender = new ListComponent(form, prompt, option, hookForCurrentPrompt); + break; + case 'autocomplete': + fieldRender = new AutoCompleteComponent(form, prompt, option, hookForCurrentPrompt); + break; + default: + fieldRender = new InputComponent(form, prompt, option, hookForCurrentPrompt); + } + await fieldRender.initState(); + promoteField.push(fieldRender); + } + + const message: Widgets.MessageElement = createValidateMessage(form.screen); + const formValidateAndSubmit = async (): Promise => { + form.submit(); + let isValidate: boolean = true; + const failedFields: Array = []; + const result: Record = {}; + for (let index: number = 0; index < promoteField.length; index++) { + try { + if (promoteField[index].isActived) { + await promoteField[index].validateResult(); + if (promoteField[index].isValidate !== true) { + isValidate = false; + failedFields.push(promoteField[index].label.getContent()); + continue; + } + const fieldName: string | undefined = promoteField[index].prompt?.name; + if (fieldName) { + result[fieldName] = form.submission[fieldName]; + } + } + } catch (e) { + form.screen.log('submit vaildate error', e); + isValidate = false; + } + } + + if (isValidate) { + return result; + } else { + message.once('element keypress', () => { + form.focus(); + message.hide(); + return false; + }); + message.focus(); + message.error( + `please fix following fields: \n${failedFields.join('\n')} \n \n press any button to continue`, + -1, + () => {} + ); + return false; + } + }; + const submitBtn: Widgets.ButtonElement = createSubmit(form, formValidateAndSubmit); + const updateFormLayout = async (): Promise => { + form.submit(); + let top: number = 0; + for (let index: number = 0; index < promoteField.length; index++) { + const pro: FieldComponent = promoteField[index]; + await pro.invokeHooks(); + await pro.when(); + pro.updateLayout({ + top: top, + height: 0 + }); + const layout: IComponentOptions = pro.getLayout(); + top = layout.top + layout?.height; + } + submitBtn.top = top; + }; + // forbidden first rotate + const firstField: Widgets.Node | undefined = promoteField[0].getFieldComponent(); + if (firstField) { + firstField.on('element keypress', (el: Widgets.Node, ch: string, key: Widgets.Events.IKeyEventArg) => { + if (key.name === 'up') { + return false; + } + }); + } + await updateFormLayout(); + form.on(CUSTOM_EMIT_EVENTS.UPDATE_LAYOUT, async () => { + await updateFormLayout(); + form.screen.render(); + }); + return { form }; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/steps.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/steps.ts new file mode 100644 index 0000000..6614fb4 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/steps.ts @@ -0,0 +1,44 @@ +import { box, layout, Widgets } from 'blessed'; +import { COLORS } from '../COLORS'; +import { PROCESS_STATUS } from '../EventManager'; +export const Steps = (): { + stepBox: Widgets.LayoutElement; + setStep: (step: number) => void; +} => { + const stepBox: Widgets.LayoutElement = layout({ + layout: 'grid', + top: 0, + shrink: true, + left: 0, + height: 3, + width: '100%' + }); + const stepsKey: number[] = [PROCESS_STATUS.TEMPLATE_SELECTING, PROCESS_STATUS.FORM_FILLING]; + const steps: string[] = ['Template Selection', 'Form Filling']; + const setStep: (step: number) => void = (step: number) => { + while (stepBox.children.length > 0) { + stepBox.children.pop(); + } + stepsKey.forEach((stepKey: number, index) => { + const stepEle: Widgets.BoxElement = box({ + tags: true, + padding: { + top: 1, + right: 2, + left: 2, + bottom: 1 + }, + content: `{center}step ${index + 1}: ${steps[index]}{/center}`, + width: '50%', + style: { + bold: stepKey === step, + bg: stepKey === step ? COLORS.blue4 : COLORS.grey0 + } + }); + stepBox.append(stepEle); + }); + stepBox.screen.render(); + }; + + return { stepBox, setStep }; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/components/templateList.ts b/rush-plugins/rush-init-project-plugin/src/ui/components/templateList.ts new file mode 100644 index 0000000..0b82fad --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/components/templateList.ts @@ -0,0 +1,29 @@ +import { list, Widgets } from 'blessed'; +import { COLORS } from '../COLORS'; + +export const TemplateList = ( + choices: { name: string; value: string }[] +): { + templateList: Widgets.ListElement; +} => { + const templateList: Widgets.ListElement = list({ + keys: true, + width: '100%', + mouse: true, + style: { + item: { + hover: { + bg: COLORS.grey0 + } + }, + selected: { + bg: COLORS.blue4, + bold: true + } + }, + items: choices.map((choice) => choice.name) + }); + + // list.focus(); + return { templateList }; +}; diff --git a/rush-plugins/rush-init-project-plugin/src/ui/index.ts b/rush-plugins/rush-init-project-plugin/src/ui/index.ts new file mode 100644 index 0000000..767059f --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/src/ui/index.ts @@ -0,0 +1,128 @@ +import blessed, { box, Widgets } from 'blessed'; +import { goNext, start, getCurrentState, PROCESS_STATUS } from './EventManager'; +import { Steps } from './components/steps'; +import { Form } from './components/form'; +import { TemplateList } from './components/templateList'; +import type { Answers } from 'inquirer'; +import type { IPluginContext } from '../logic/TemplateConfiguration'; +import type { NodePlopAPI, PlopCfg, PromptQuestion } from 'node-plop'; +import { ICliParams } from '../init-project'; +import { COLORS } from './COLORS'; +import { Warning } from './components/Warning'; +import { CUSTOM_EMIT_EVENTS } from './EMIT_EVENTS'; +import { TerminalSingleton } from '../terminal'; + +export const initBlessedForm = async ( + promptQueue: Array, + pluginContext: IPluginContext, + plop: NodePlopAPI, + plopCfg: PlopCfg & ICliParams, + loadTemplateConfiguration: (promptQueue: PromptQuestion[], template: string) => Promise, + templateChoices: { name: string; value: string }[] +): Promise => { + const screen: Widgets.Screen = blessed.screen({ + debug: plopCfg.verbose, + dump: plopCfg.verbose, + log: plopCfg.verbose ? './blessed.log' : undefined, + dockBorders: true, + transparent: true, + smartCSR: true, + useBCE: true, + terminal: 'xterm-256color', + fullUnicode: true + }); + const { stepBox, setStep } = Steps(); + const { WarningBox, setWarningContent } = Warning(); + screen.append(stepBox); + screen.append(WarningBox); + // exits the process + screen.program.key(['C-c'], () => { + return process.exit(0); + }); + screen.on('resize', () => { + screen.render(); + }); + start(); + let answers: Answers = {}; + let template: string = ''; + if (getCurrentState() === PROCESS_STATUS.TEMPLATE_SELECTING) { + setWarningContent('move with ⬇/⬆ press space or enter to next stage. Exit with Ctrl+c.'); + setStep(PROCESS_STATUS.TEMPLATE_SELECTING); + const templateBox: Widgets.BoxElement = box({ + parent: screen, + top: 4, + width: '100%', + height: '100%-5' + }); + const { templateList } = TemplateList(templateChoices); + templateBox.append(templateList); + templateList.focus(); + screen.render(); + template = await new Promise((resolve, reject) => { + let selectedItem: string = templateChoices[0].value; + templateList.on('select', function (el: Widgets.Node, selected: number) { + selectedItem = templateChoices[selected].value; + if (templateList._.rendering) return; + }); + templateList.children.forEach(function (item: Widgets.Node, index: number) { + item.on('click', () => { + selectedItem = templateChoices[index].value; + screen.remove(templateBox); + resolve(selectedItem); + }); + }); + templateList.key(['return'], function () { + screen.remove(templateBox); + resolve(selectedItem); + }); + templateList.key(['space'], function () { + templateList.emit('keypress', '\r', { name: 'enter' }); + }); + }); + await loadTemplateConfiguration(promptQueue, template); + goNext(); + } + if (getCurrentState() === PROCESS_STATUS.FORM_FILLING) { + setWarningContent('move with ⬇/⬆ or tab. Exit with Ctrl+c.'); + setStep(PROCESS_STATUS.FORM_FILLING); + const formBox: Widgets.BoxElement = box({ + parent: screen, + top: 4, + tags: true, + width: '100%', + height: '100%-5', + content: `Selected Template: {${COLORS.blue4}}${template}{/${COLORS.blue4}}` + }); + try { + const { form } = await Form(promptQueue); + formBox.append(form); + + form.focusNext(); + screen.render(); + answers = await new Promise((resolve) => { + form.on(CUSTOM_EMIT_EVENTS.SUBMIT_ANSWERS, (res) => { + if (res) { + resolve(res); + } + }); + }); + } catch (error: any) { + screen.log(error); + TerminalSingleton.getInstance().writeErrorLine((error ?? 'error')?.toString()); + process.exit(1); + } + goNext(); + } + // if(getCurrentState() === PROCESS_STATUS.ACTIONS_INVOKING){ + // goNext(); + // } + // if(getCurrentState() === PROCESS_STATUS.FINISHED){ + + // } + TerminalSingleton.getInstance().writeVerboseLine(`answers: `); + screen.destroy(); + return { + template, + ...answers + }; +}; diff --git a/rush-plugins/rush-init-project-plugin/tsconfig.json b/rush-plugins/rush-init-project-plugin/tsconfig.json new file mode 100644 index 0000000..4343a32 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "resolveJsonModule": true /* Enable importing .json files */, + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-init-project-plugin/typings.d.ts b/rush-plugins/rush-init-project-plugin/typings.d.ts new file mode 100644 index 0000000..8c2edb5 --- /dev/null +++ b/rush-plugins/rush-init-project-plugin/typings.d.ts @@ -0,0 +1,5 @@ +declare module 'validate-npm-package-name'; + +declare module 'handlebars-helpers*'; + +declare module 'blessed/lib/widgets/*'; diff --git a/rush-plugins/rush-lint-staged-plugin/.eslintrc.js b/rush-plugins/rush-lint-staged-plugin/.eslintrc.js new file mode 100644 index 0000000..0663598 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// // This is a workaround for https://github.com/eslint/eslint/issues/3458 +// require("@rushstack/eslint-config/patch/modern-module-resolution"); + +// module.exports = { +// extends: [ +// "@rushstack/eslint-config/profile/node-trusted-tool", +// "@rushstack/eslint-config/mixins/friendly-locals", +// ], +// parserOptions: { tsconfigRootDir: __dirname }, +// ignorePatterns: ["node_modules/", "lib/"], +// rules: { +// "@typescript-eslint/no-explicit-any": "off", +// }, +// }; diff --git a/rush-plugins/rush-lint-staged-plugin/.gitignore b/rush-plugins/rush-lint-staged-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-lint-staged-plugin/.npmignore b/rush-plugins/rush-lint-staged-plugin/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-lint-staged-plugin/CHANGELOG.json b/rush-plugins/rush-lint-staged-plugin/CHANGELOG.json new file mode 100644 index 0000000..d660ef4 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/CHANGELOG.json @@ -0,0 +1,101 @@ +{ + "name": "rush-lint-staged-plugin", + "entries": [ + { + "version": "0.1.6", + "tag": "rush-lint-staged-plugin_v0.1.6", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.1.5", + "tag": "rush-lint-staged-plugin_v0.1.5", + "date": "Mon, 13 Jun 2022 02:59:04 GMT", + "comments": { + "patch": [ + { + "comment": "Update only" + } + ] + } + }, + { + "version": "0.1.4", + "tag": "rush-lint-staged-plugin_v0.1.4", + "date": "Mon, 13 Jun 2022 02:56:11 GMT", + "comments": { + "patch": [ + { + "comment": "Exit with code 1 if linting failed" + } + ] + } + }, + { + "version": "0.1.3", + "tag": "rush-lint-staged-plugin_v0.1.3", + "date": "Tue, 22 Mar 2022 03:26:29 GMT", + "comments": { + "patch": [ + { + "comment": "something change" + } + ] + } + }, + { + "version": "0.1.2", + "tag": "rush-lint-staged-plugin_v0.1.2", + "date": "Thu, 24 Feb 2022 11:57:31 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade lint-staged" + } + ] + } + }, + { + "version": "0.1.1", + "tag": "rush-lint-staged-plugin_v0.1.1", + "date": "Thu, 03 Feb 2022 11:45:46 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade lint-staged to 12.3.3" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-lint-staged-plugin_v0.1.0", + "date": "Thu, 03 Feb 2022 11:43:28 GMT", + "comments": { + "minor": [ + { + "comment": "Upgrade lint-staged to 12.3.3 with fixing cwd for subtasks" + } + ] + } + }, + { + "version": "0.0.1", + "tag": "rush-lint-staged-plugin_v0.0.1", + "date": "Wed, 19 Jan 2022 15:06:25 GMT", + "comments": { + "patch": [ + { + "comment": "First implementation" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-lint-staged-plugin/CHANGELOG.md b/rush-plugins/rush-lint-staged-plugin/CHANGELOG.md new file mode 100644 index 0000000..1d8bdc6 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/CHANGELOG.md @@ -0,0 +1,60 @@ +# Change Log - rush-lint-staged-plugin + +This log was last generated on Wed, 31 Aug 2022 04:09:13 GMT and should not be manually modified. + +## 0.1.6 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme + +## 0.1.5 +Mon, 13 Jun 2022 02:59:04 GMT + +### Patches + +- Update only + +## 0.1.4 +Mon, 13 Jun 2022 02:56:11 GMT + +### Patches + +- Exit with code 1 if linting failed + +## 0.1.3 +Tue, 22 Mar 2022 03:26:29 GMT + +### Patches + +- something change + +## 0.1.2 +Thu, 24 Feb 2022 11:57:31 GMT + +### Patches + +- Upgrade lint-staged + +## 0.1.1 +Thu, 03 Feb 2022 11:45:46 GMT + +### Patches + +- Upgrade lint-staged to 12.3.3 + +## 0.1.0 +Thu, 03 Feb 2022 11:43:28 GMT + +### Minor changes + +- Upgrade lint-staged to 12.3.3 with fixing cwd for subtasks + +## 0.0.1 +Wed, 19 Jan 2022 15:06:25 GMT + +### Patches + +- First implementation + diff --git a/rush-plugins/rush-lint-staged-plugin/LICENSE b/rush-plugins/rush-lint-staged-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-lint-staged-plugin/README.md b/rush-plugins/rush-lint-staged-plugin/README.md new file mode 100644 index 0000000..c54709a --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/README.md @@ -0,0 +1,68 @@ +# rush-lint-staged-plugin + +Rush plugin for lint-staged + +# Prerequisite + +- Rush.js >= 5.57.0 +- Node >= 12 + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Running `lint-staged` + +``` +rush lint-staged +``` + +3. Set up Git `pre-commit` hook + +**common/git-hooks/pre-commit** + +``` +#!/bin/sh + +node common/scripts/install-run-rush.js lint-staged || exit $? +``` + +4. Add a placeholder `lint-staged` config in root path. + +The reason of adding this file is the fact that `lint-staged` behaves differently with the number of config files. With this placeholder config, `lint-staged` will always find multiple config files in your monorepo, which corrects the working directory of each task. + +**/.lintstagedrc.json** + +``` +{ + "*": "echo ok" +} +``` + +# Rational + +`lint-staged@>=12.2.1` supports a new feature called multiple config files. With this feature, each staged files can load different lint-staged configuration. This plugin invokes `lintStaged` for you. No more no less. + +For example, + +``` +monorepo-root +├── scripts +| └── index.js +├── apps/my-app +| ├── index.js +| └── .lintstagedrc.js +└── libraries/my-lib + ├── index.js + └── .lintstagedrc.js +``` + +Assuming git staged `apps/my-app/index.js`, `libraries/my-lib/index.js` and `scripts/index.js` + +when `rush lint-staged` runs, + +1. `apps/my-app/index.js` uses config from `apps/my-app/.lintstagedrc.js` +2. `libraries/my-lib/index.js` uses config from `libraries/my-lib/.lintstagedrc.js` +3. `scripts/index.js` has no related config, nothing runs for this file diff --git a/rush-plugins/rush-lint-staged-plugin/command-line.json b/rush-plugins/rush-lint-staged-plugin/command-line.json new file mode 100644 index 0000000..ad4c779 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "lint-staged", + "commandKind": "global", + "summary": "Rush plugin for lint-staged", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/rush-plugins/rush-lint-staged-plugin/config/heft.json b/rush-plugins/rush-lint-staged-plugin/config/heft.json new file mode 100644 index 0000000..a602554 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/config/heft.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ] +} diff --git a/rush-plugins/rush-lint-staged-plugin/lint-staged.config.cjs b/rush-plugins/rush-lint-staged-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-lint-staged-plugin/package.json b/rush-plugins/rush-lint-staged-plugin/package.json new file mode 100644 index 0000000..13c084b --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/package.json @@ -0,0 +1,43 @@ +{ + "name": "rush-lint-staged-plugin", + "version": "0.1.6", + "description": "Rush plugin for lint-staged", + "keywords": [ + "rush", + "plugin", + "command" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-lint-staged-plugin" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": "./lib/index.mjs" + }, + "scripts": { + "build": "heft build --clean --lite", + "build:watch": "heft build --lite --watch", + "prepublishOnly": "npm run build", + "test": "" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "lint-staged": "12.3.4" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } +} diff --git a/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json b/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..4d41939 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-lint-staged-plugin", + "description": "Rush plugin for lint-staged", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-lint-staged-plugin/src/helpers/terminal.ts b/rush-plugins/rush-lint-staged-plugin/src/helpers/terminal.ts new file mode 100644 index 0000000..d9b548f --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/src/helpers/terminal.ts @@ -0,0 +1,6 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; + +export const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); diff --git a/rush-plugins/rush-lint-staged-plugin/src/index.ts b/rush-plugins/rush-lint-staged-plugin/src/index.ts new file mode 100644 index 0000000..70a3f90 --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/src/index.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env node + +import lintStaged from 'lint-staged'; + +// import { terminal } from "./helpers/terminal.mjs"; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + // https://github.com/okonet/lint-staged/pull/1080 + const success = await lintStaged(); + if (!success) process.exit(1); + } catch (error: any) { + if (error.message) { + // terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/rush-plugins/rush-lint-staged-plugin/src/typings.d.ts b/rush-plugins/rush-lint-staged-plugin/src/typings.d.ts new file mode 100644 index 0000000..f9ebfce --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/src/typings.d.ts @@ -0,0 +1 @@ +declare module 'lint-staged'; \ No newline at end of file diff --git a/rush-plugins/rush-lint-staged-plugin/tsconfig.json b/rush-plugins/rush-lint-staged-plugin/tsconfig.json new file mode 100644 index 0000000..25d0cae --- /dev/null +++ b/rush-plugins/rush-lint-staged-plugin/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2020" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "ES2020" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/.eslintrc.js b/rush-plugins/rush-print-log-if-error-plugin/.eslintrc.js new file mode 100644 index 0000000..925d67c --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-print-log-if-error-plugin/.gitignore b/rush-plugins/rush-print-log-if-error-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.json b/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.json new file mode 100644 index 0000000..43703b2 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.json @@ -0,0 +1,65 @@ +{ + "name": "rush-print-log-if-error-plugin", + "entries": [ + { + "version": "0.0.5", + "tag": "rush-print-log-if-error-plugin_v0.0.5", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.0.4", + "tag": "rush-print-log-if-error-plugin_v0.0.4", + "date": "Thu, 24 Feb 2022 11:57:31 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade rush-sdk to load rushConfiguration" + } + ] + } + }, + { + "version": "0.0.3", + "tag": "rush-print-log-if-error-plugin_v0.0.3", + "date": "Mon, 10 Jan 2022 06:10:29 GMT", + "comments": { + "patch": [ + { + "comment": "Refactor cat with readline" + } + ] + } + }, + { + "version": "0.0.2", + "tag": "rush-print-log-if-error-plugin_v0.0.2", + "date": "Mon, 10 Jan 2022 04:06:08 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme only" + } + ] + } + }, + { + "version": "0.0.1", + "tag": "rush-print-log-if-error-plugin_v0.0.1", + "date": "Mon, 10 Jan 2022 03:46:23 GMT", + "comments": { + "patch": [ + { + "comment": "Initial implementation" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.md b/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.md new file mode 100644 index 0000000..aaf00e5 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/CHANGELOG.md @@ -0,0 +1,39 @@ +# Change Log - rush-print-log-if-error-plugin + +This log was last generated on Wed, 31 Aug 2022 04:09:13 GMT and should not be manually modified. + +## 0.0.5 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme + +## 0.0.4 +Thu, 24 Feb 2022 11:57:31 GMT + +### Patches + +- Upgrade rush-sdk to load rushConfiguration + +## 0.0.3 +Mon, 10 Jan 2022 06:10:29 GMT + +### Patches + +- Refactor cat with readline + +## 0.0.2 +Mon, 10 Jan 2022 04:06:08 GMT + +### Patches + +- Update readme only + +## 0.0.1 +Mon, 10 Jan 2022 03:46:23 GMT + +### Patches + +- Initial implementation + diff --git a/rush-plugins/rush-print-log-if-error-plugin/LICENSE b/rush-plugins/rush-print-log-if-error-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-print-log-if-error-plugin/README.md b/rush-plugins/rush-print-log-if-error-plugin/README.md new file mode 100644 index 0000000..c740c1a --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/README.md @@ -0,0 +1,32 @@ +# rush-print-log-if-error-plugin + +Rush plugin for print entire log if error log exists + +# Prerequisite + +Rush.js >= 5.57.0 + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Print log if error log exists + +``` +rush print-log-if-error +``` + +If `.build.error.log` exists, print the content of `.build.log` + +## Advance Usage + +```bash +#!/bin/bash + +# logout if error +trap "node common/scripts/install-run-rush.js print-log-if-error" ERR + +node common/scripts/install-run-rush.js build +``` \ No newline at end of file diff --git a/rush-plugins/rush-print-log-if-error-plugin/command-line.json b/rush-plugins/rush-print-log-if-error-plugin/command-line.json new file mode 100644 index 0000000..e1558a6 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "print-log-if-error", + "commandKind": "global", + "summary": "Rush plugin for print entire log if error log exists", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/config/heft.json b/rush-plugins/rush-print-log-if-error-plugin/config/heft.json new file mode 100644 index 0000000..a602554 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/config/heft.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ] +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/lint-staged.config.cjs b/rush-plugins/rush-print-log-if-error-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-print-log-if-error-plugin/package.json b/rush-plugins/rush-print-log-if-error-plugin/package.json new file mode 100644 index 0000000..9125ad7 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/package.json @@ -0,0 +1,39 @@ +{ + "name": "rush-print-log-if-error-plugin", + "version": "0.0.5", + "description": "Rush plugin for print entire log if error log exists", + "keywords": [ + "rush", + "plugin", + "command", + "print", + "log" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-print-log-if-error-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/rush-plugin-manifest.json b/rush-plugins/rush-print-log-if-error-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..09f493b --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-print-log-if-error-plugin", + "description": "Rush plugin for print entire log if error log exists", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/src/helpers/loadRushConfiguration.ts b/rush-plugins/rush-print-log-if-error-plugin/src/helpers/loadRushConfiguration.ts new file mode 100644 index 0000000..f241672 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/src/helpers/loadRushConfiguration.ts @@ -0,0 +1,23 @@ +import { RushConfiguration } from "@rushstack/rush-sdk"; + +const cwd2RushConfiguration: Record = {}; + +export const loadRushConfiguration = ( + cwd: string = process.cwd() +): RushConfiguration => { + let rushConfiguration: RushConfiguration = cwd2RushConfiguration[cwd]; + if (!rushConfiguration) { + try { + rushConfiguration = RushConfiguration.loadFromDefaultLocation({ + startingFolder: cwd, + }); + if (!rushConfiguration) { + throw new Error("Rush configuration not found"); + } + cwd2RushConfiguration[cwd] = rushConfiguration; + } catch (e) { + throw new Error("Load rush configuration failed"); + } + } + return rushConfiguration; +}; diff --git a/rush-plugins/rush-print-log-if-error-plugin/src/helpers/terminal.ts b/rush-plugins/rush-print-log-if-error-plugin/src/helpers/terminal.ts new file mode 100644 index 0000000..d9b548f --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/src/helpers/terminal.ts @@ -0,0 +1,6 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; + +export const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); diff --git a/rush-plugins/rush-print-log-if-error-plugin/src/index.ts b/rush-plugins/rush-print-log-if-error-plugin/src/index.ts new file mode 100644 index 0000000..651ef9c --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/src/index.ts @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +import path from "path"; +import fs from "fs"; +import readline from "readline"; + +import { loadRushConfiguration } from "./helpers/loadRushConfiguration"; +import { terminal } from "./helpers/terminal"; + +import type { RushConfiguration } from "@rushstack/rush-sdk"; +import type { PackageNameParser } from "@rushstack/node-core-library"; +import type { ReadStream } from "fs"; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + const rushConfig: RushConfiguration = loadRushConfiguration(); + + const packageNameParser: PackageNameParser = + rushConfig.packageNameParser as unknown as PackageNameParser; + let hasPrint: boolean = false; + for (const project of rushConfig.projects) { + const folder: string = project.projectFolder; + const unscopedProjectName: string = packageNameParser.getUnscopedName( + project.packageName + ); + const buildLogPath: string = path.resolve( + folder, + `${unscopedProjectName}.build.log` + ); + const buildErrorLogPath: string = path.resolve( + folder, + `${unscopedProjectName}.build.error.log` + ); + if (fs.existsSync(buildErrorLogPath) && fs.existsSync(buildLogPath)) { + const readStream: ReadStream = fs.createReadStream(buildLogPath); + console.log(`========== ${project.packageName} BEGIN ==========`); + const rl: readline.Interface = readline.createInterface({ + input: readStream, + output: process.stdout, + }); + let resolve: () => void = null as unknown as () => void; + // eslint-disable-next-line promise/param-names, @typescript-eslint/naming-convention + const p: Promise = new Promise((_resolve: () => void) => { + const timeoutId: NodeJS.Timeout = setTimeout(() => { + console.log(`========== ${project.packageName} TIMEOUT ==========`); + _resolve(); + }, 60 * 1000); + resolve = () => { + clearTimeout(timeoutId); + _resolve(); + }; + }); + rl.on("close", () => { + resolve(); + console.log(`========== ${project.packageName} END ==========`); + }); + await p; + hasPrint = true; + } + } + if (!hasPrint) { + console.log( + `[print-log-if-error] I am not the culprit!!! Please scroll up to check the real error.` + ); + } + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/rush-plugins/rush-print-log-if-error-plugin/tsconfig.json b/rush-plugins/rush-print-log-if-error-plugin/tsconfig.json new file mode 100644 index 0000000..82917d2 --- /dev/null +++ b/rush-plugins/rush-print-log-if-error-plugin/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-sort-package-json/.eslintrc.js b/rush-plugins/rush-sort-package-json/.eslintrc.js new file mode 100644 index 0000000..925d67c --- /dev/null +++ b/rush-plugins/rush-sort-package-json/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-sort-package-json/.gitignore b/rush-plugins/rush-sort-package-json/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-sort-package-json/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-sort-package-json/CHANGELOG.json b/rush-plugins/rush-sort-package-json/CHANGELOG.json new file mode 100644 index 0000000..3e8aefb --- /dev/null +++ b/rush-plugins/rush-sort-package-json/CHANGELOG.json @@ -0,0 +1,41 @@ +{ + "name": "rush-sort-package-json", + "entries": [ + { + "version": "0.0.4", + "tag": "rush-sort-package-json_v0.0.4", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "0.0.3", + "tag": "rush-sort-package-json_v0.0.3", + "date": "Sat, 11 Jun 2022 08:01:34 GMT", + "comments": { + "patch": [ + { + "comment": "Mark as safe for simultaneous processes" + } + ] + } + }, + { + "version": "0.0.2", + "tag": "rush-sort-package-json_v0.0.2", + "date": "Tue, 22 Mar 2022 03:26:29 GMT", + "comments": { + "patch": [ + { + "comment": "init" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-sort-package-json/CHANGELOG.md b/rush-plugins/rush-sort-package-json/CHANGELOG.md new file mode 100644 index 0000000..ffc9d95 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/CHANGELOG.md @@ -0,0 +1,25 @@ +# Change Log - rush-sort-package-json + +This log was last generated on Wed, 31 Aug 2022 04:09:13 GMT and should not be manually modified. + +## 0.0.4 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme + +## 0.0.3 +Sat, 11 Jun 2022 08:01:34 GMT + +### Patches + +- Mark as safe for simultaneous processes + +## 0.0.2 +Tue, 22 Mar 2022 03:26:29 GMT + +### Patches + +- init + diff --git a/rush-plugins/rush-sort-package-json/LICENSE b/rush-plugins/rush-sort-package-json/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-sort-package-json/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-sort-package-json/README.md b/rush-plugins/rush-sort-package-json/README.md new file mode 100644 index 0000000..63bf4c5 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/README.md @@ -0,0 +1,33 @@ +# rush-sort-package-json + +Rush plugin for sort package.json file in the project. + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Running `sort-package-json` + +``` +rush sort-package-json +``` + +# What is the plugin for? + +We have noticed that: + +1. There is some feedback about the package.json file under the rush repository being out of order. +2. `rush add` only puts the added dependencies at the end of the deps field. + +Therefore, this command will sort all package.json files in the rush repository. + +# Q: Why not modify the `rush add` command to keep it in order? + +A: Because many other commands may also change package.json, such as `rush version --bump` or manually modify dependencies. + +# Related issues + + +[rushstack #2496](https://github.com/microsoft/rushstack/issues/2496) diff --git a/rush-plugins/rush-sort-package-json/command-line.json b/rush-plugins/rush-sort-package-json/command-line.json new file mode 100644 index 0000000..5fdf60c --- /dev/null +++ b/rush-plugins/rush-sort-package-json/command-line.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "sort-package-json", + "commandKind": "global", + "summary": "Rush plugin for sort package.json file in the project", + "shellCommand": "node /lib/index.js", + "safeForSimultaneousRushProcesses": true + } + ] +} \ No newline at end of file diff --git a/rush-plugins/rush-sort-package-json/config/heft.json b/rush-plugins/rush-sort-package-json/config/heft.json new file mode 100644 index 0000000..a602554 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/config/heft.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ] +} diff --git a/rush-plugins/rush-sort-package-json/lint-staged.config.cjs b/rush-plugins/rush-sort-package-json/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-sort-package-json/package.json b/rush-plugins/rush-sort-package-json/package.json new file mode 100644 index 0000000..d1bfbe5 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/package.json @@ -0,0 +1,40 @@ +{ + "name": "rush-sort-package-json", + "version": "0.0.4", + "description": "Rush plugin for sort package.json file in the project", + "keywords": [ + "rush", + "plugin", + "command", + "sort", + "package.json" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "repository": { + "type": "git", + "url": "https://github.com/tiktok/rush-plugins", + "directory": "rush-plugins/rush-sort-package-json" + }, + "license": "MIT", + "main": "lib/index.js", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "sort-package-json": "1.54.0" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/node": "12.20.24", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json b/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json new file mode 100644 index 0000000..2ff4b5f --- /dev/null +++ b/rush-plugins/rush-sort-package-json/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-sort-package-json", + "description": "Rush plugin for sort package.json file in the project", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-sort-package-json/src/helpers/loadRushConfiguration.ts b/rush-plugins/rush-sort-package-json/src/helpers/loadRushConfiguration.ts new file mode 100644 index 0000000..f241672 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/src/helpers/loadRushConfiguration.ts @@ -0,0 +1,23 @@ +import { RushConfiguration } from "@rushstack/rush-sdk"; + +const cwd2RushConfiguration: Record = {}; + +export const loadRushConfiguration = ( + cwd: string = process.cwd() +): RushConfiguration => { + let rushConfiguration: RushConfiguration = cwd2RushConfiguration[cwd]; + if (!rushConfiguration) { + try { + rushConfiguration = RushConfiguration.loadFromDefaultLocation({ + startingFolder: cwd, + }); + if (!rushConfiguration) { + throw new Error("Rush configuration not found"); + } + cwd2RushConfiguration[cwd] = rushConfiguration; + } catch (e) { + throw new Error("Load rush configuration failed"); + } + } + return rushConfiguration; +}; diff --git a/rush-plugins/rush-sort-package-json/src/helpers/terminal.ts b/rush-plugins/rush-sort-package-json/src/helpers/terminal.ts new file mode 100644 index 0000000..d9b548f --- /dev/null +++ b/rush-plugins/rush-sort-package-json/src/helpers/terminal.ts @@ -0,0 +1,6 @@ +import { + Terminal, + ConsoleTerminalProvider, +} from "@rushstack/node-core-library"; + +export const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); diff --git a/rush-plugins/rush-sort-package-json/src/index.ts b/rush-plugins/rush-sort-package-json/src/index.ts new file mode 100644 index 0000000..11095e3 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/src/index.ts @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +import path from "path"; + +import { loadRushConfiguration } from "./helpers/loadRushConfiguration"; +import { terminal } from "./helpers/terminal"; + +import type { RushConfiguration } from "@rushstack/rush-sdk"; +import { sortPackageJson } from "./sortPackageJson"; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + const rushConfig: RushConfiguration = loadRushConfiguration(); + for (const project of rushConfig.projects) { + const packageJsonFilePath: string = path.resolve( + rushConfig.rushJsonFolder, + project.projectFolder + ); + sortPackageJson(packageJsonFilePath); + } + terminal.writeLine('sort package.json successfully'); + } catch (error: any) { + if (error.message) { + terminal.writeErrorLine(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/rush-plugins/rush-sort-package-json/src/sortPackageJson.ts b/rush-plugins/rush-sort-package-json/src/sortPackageJson.ts new file mode 100644 index 0000000..a114ad5 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/src/sortPackageJson.ts @@ -0,0 +1,12 @@ +import path from "path"; +import { FileSystem } from "@rushstack/node-core-library"; +import sort from "sort-package-json"; + +export const sortPackageJson = (projectPath: string): void => { + const packageJsonFilePath: string = path.resolve(projectPath, "package.json"); + if (!FileSystem.exists(packageJsonFilePath)) { + throw new Error(`package.json for ${packageJsonFilePath} does not exist`); + } + const input: string = FileSystem.readFile(packageJsonFilePath); + FileSystem.writeFile(packageJsonFilePath, sort(input)); +}; diff --git a/rush-plugins/rush-sort-package-json/tsconfig.json b/rush-plugins/rush-sort-package-json/tsconfig.json new file mode 100644 index 0000000..82917d2 --- /dev/null +++ b/rush-plugins/rush-sort-package-json/tsconfig.json @@ -0,0 +1,97 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES2015" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush-plugins/rush-upgrade-self-plugin/.eslintrc.js b/rush-plugins/rush-upgrade-self-plugin/.eslintrc.js new file mode 100644 index 0000000..925d67c --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/.eslintrc.js @@ -0,0 +1,14 @@ +// This is a workaround for https://github.com/eslint/eslint/issues/3458 +require("@rushstack/eslint-config/patch/modern-module-resolution"); + +module.exports = { + extends: [ + "@rushstack/eslint-config/profile/node-trusted-tool", + "@rushstack/eslint-config/mixins/friendly-locals", + ], + parserOptions: { tsconfigRootDir: __dirname }, + ignorePatterns: ["node_modules/", "lib/"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + }, +}; diff --git a/rush-plugins/rush-upgrade-self-plugin/.gitignore b/rush-plugins/rush-upgrade-self-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/rush-plugins/rush-upgrade-self-plugin/.npmignore b/rush-plugins/rush-upgrade-self-plugin/.npmignore new file mode 100644 index 0000000..f6463aa --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/.npmignore @@ -0,0 +1,34 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!ThirdPartyNotice.txt +!/src/** + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README (and its variants) +# CHANGELOG (and its variants) +# LICENSE / LICENCE + +#-------------------------------------------- +# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE +#-------------------------------------------- + +# (Add your project-specific overrides here) +!/includes/** +!rush-plugin-manifest.json +!command-line.json diff --git a/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.json b/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.json new file mode 100644 index 0000000..41f7d28 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.json @@ -0,0 +1,154 @@ +{ + "name": "rush-upgrade-self-plugin", + "entries": [ + { + "version": "1.0.7", + "tag": "rush-upgrade-self-plugin_v1.0.7", + "date": "Wed, 31 Aug 2022 04:09:13 GMT", + "comments": { + "patch": [ + { + "comment": "Update readme" + } + ] + } + }, + { + "version": "1.0.6", + "tag": "rush-upgrade-self-plugin_v1.0.6", + "date": "Thu, 24 Feb 2022 11:57:31 GMT", + "comments": { + "patch": [ + { + "comment": "Upgrade rush-sdk to load rushConfiguration" + } + ] + } + }, + { + "version": "1.0.5", + "tag": "rush-upgrade-self-plugin_v1.0.5", + "date": "Thu, 16 Dec 2021 16:10:36 GMT", + "comments": { + "patch": [ + { + "comment": "Update @rushstack/rush-sdk version as well" + } + ] + } + }, + { + "version": "1.0.4", + "tag": "rush-upgrade-self-plugin_v1.0.4", + "date": "Mon, 13 Dec 2021 00:58:24 GMT", + "comments": { + "patch": [ + { + "comment": "update readme" + } + ] + } + }, + { + "version": "1.0.3", + "tag": "rush-upgrade-self-plugin_v1.0.3", + "date": "Fri, 10 Dec 2021 08:54:01 GMT", + "comments": { + "patch": [ + { + "comment": "update readme only" + } + ] + } + }, + { + "version": "1.0.2", + "tag": "rush-upgrade-self-plugin_v1.0.2", + "date": "Fri, 10 Dec 2021 03:27:48 GMT", + "comments": { + "patch": [ + { + "comment": "pretty log" + } + ] + } + }, + { + "version": "1.0.1", + "tag": "rush-upgrade-self-plugin_v1.0.1", + "date": "Fri, 10 Dec 2021 02:55:26 GMT", + "comments": { + "patch": [ + { + "comment": "fix run rush update" + } + ] + } + }, + { + "version": "1.0.0", + "tag": "rush-upgrade-self-plugin_v1.0.0", + "date": "Thu, 09 Dec 2021 19:50:06 GMT", + "comments": { + "patch": [ + { + "comment": "fix update autoinstaller" + } + ], + "major": [ + { + "comment": "first formal release" + } + ] + } + }, + { + "version": "0.4.0", + "tag": "rush-upgrade-self-plugin_v0.4.0", + "date": "Thu, 09 Dec 2021 19:33:35 GMT", + "comments": { + "minor": [ + { + "comment": "ignore invalid package.json'" + } + ] + } + }, + { + "version": "0.3.0", + "tag": "rush-upgrade-self-plugin_v0.3.0", + "date": "Thu, 09 Dec 2021 19:08:21 GMT", + "comments": { + "minor": [ + { + "comment": "add workaround for rush-sdk" + } + ] + } + }, + { + "version": "0.2.0", + "tag": "rush-upgrade-self-plugin_v0.2.0", + "date": "Thu, 09 Dec 2021 18:03:31 GMT", + "comments": { + "minor": [ + { + "comment": "should not ignore command-line.json" + } + ] + } + }, + { + "version": "0.1.0", + "tag": "rush-upgrade-self-plugin_v0.1.0", + "date": "Thu, 09 Dec 2021 17:50:47 GMT", + "comments": { + "minor": [ + { + "comment": "initial implementation" + } + ] + } + } + ] +} diff --git a/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.md b/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.md new file mode 100644 index 0000000..08605d9 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/CHANGELOG.md @@ -0,0 +1,92 @@ +# Change Log - rush-upgrade-self-plugin + +This log was last generated on Wed, 31 Aug 2022 04:09:13 GMT and should not be manually modified. + +## 1.0.7 +Wed, 31 Aug 2022 04:09:13 GMT + +### Patches + +- Update readme + +## 1.0.6 +Thu, 24 Feb 2022 11:57:31 GMT + +### Patches + +- Upgrade rush-sdk to load rushConfiguration + +## 1.0.5 +Thu, 16 Dec 2021 16:10:36 GMT + +### Patches + +- Update @rushstack/rush-sdk version as well + +## 1.0.4 +Mon, 13 Dec 2021 00:58:24 GMT + +### Patches + +- update readme + +## 1.0.3 +Fri, 10 Dec 2021 08:54:01 GMT + +### Patches + +- update readme only + +## 1.0.2 +Fri, 10 Dec 2021 03:27:48 GMT + +### Patches + +- pretty log + +## 1.0.1 +Fri, 10 Dec 2021 02:55:26 GMT + +### Patches + +- fix run rush update + +## 1.0.0 +Thu, 09 Dec 2021 19:50:06 GMT + +### Breaking changes + +- first formal release + +### Patches + +- fix update autoinstaller + +## 0.4.0 +Thu, 09 Dec 2021 19:33:35 GMT + +### Minor changes + +- ignore invalid package.json' + +## 0.3.0 +Thu, 09 Dec 2021 19:08:21 GMT + +### Minor changes + +- add workaround for rush-sdk + +## 0.2.0 +Thu, 09 Dec 2021 18:03:31 GMT + +### Minor changes + +- should not ignore command-line.json + +## 0.1.0 +Thu, 09 Dec 2021 17:50:47 GMT + +### Minor changes + +- initial implementation + diff --git a/rush-plugins/rush-upgrade-self-plugin/LICENSE b/rush-plugins/rush-upgrade-self-plugin/LICENSE new file mode 100644 index 0000000..3bd1dad --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) TikTok Pte. Ltd. + +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/rush-plugins/rush-upgrade-self-plugin/README.md b/rush-plugins/rush-upgrade-self-plugin/README.md new file mode 100644 index 0000000..bdce005 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/README.md @@ -0,0 +1,32 @@ +# rush-upgrade-self-plugin + +Rush plugin for upgrade Rush.js itself in monorepo. + +# Prerequisite + +Rush.js >= 5.57.0 + +# Quick Start + +1. Enabling this rush plugin + +Please follow the [official doc](https://rushjs.io/pages/maintainer/using_rush_plugins/) to enable this plugin in your repo. + +2. Upgrade Rush.js + +``` +rush upgrade-self +``` + +## Working process + +1. Fetch `microsoft/rush` versions by `pacote` +2. Prompt user to choose a version, which decides the target versions of dependencies should be updated.(Those who prefixes with `@microsoft/` or `@rushstack/`) +3. Update dependencies(including devDependencies) in all `package.json` files +4. Update autoinstallers accordingly. +5. Prompt user whether to run `rush update` + +# Something went wrong? + +- Run `git checkout .` to revert all changes by this plugin. +- This plugin is designed to be idempotent. just run it again! \ No newline at end of file diff --git a/rush-plugins/rush-upgrade-self-plugin/command-line.json b/rush-plugins/rush-upgrade-self-plugin/command-line.json new file mode 100644 index 0000000..276e127 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/command-line.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "name": "upgrade-self", + "commandKind": "global", + "summary": "Upgrade Rush.js itself", + "shellCommand": "rush-upgrade-self", + "safeForSimultaneousRushProcesses": true + } + ] + // "parameters": [], +} diff --git a/rush-plugins/rush-upgrade-self-plugin/config/heft.json b/rush-plugins/rush-upgrade-self-plugin/config/heft.json new file mode 100644 index 0000000..a602554 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/config/heft.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json", + + "eventActions": [ + { + "actionKind": "deleteGlobs", + "heftEvent": "clean", + "actionId": "defaultClean", + "globsToDelete": ["lib"] + } + ] +} diff --git a/rush-plugins/rush-upgrade-self-plugin/lint-staged.config.cjs b/rush-plugins/rush-upgrade-self-plugin/lint-staged.config.cjs new file mode 100644 index 0000000..33e35b9 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/lint-staged.config.cjs @@ -0,0 +1,5 @@ +/* eslint-env es6 */ +const config = { + "*.{js,jsx,ts,tsx}": "eslint --fix", +}; +module.exports = config; diff --git a/rush-plugins/rush-upgrade-self-plugin/package.json b/rush-plugins/rush-upgrade-self-plugin/package.json new file mode 100644 index 0000000..0eb0d7a --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/package.json @@ -0,0 +1,50 @@ +{ + "name": "rush-upgrade-self-plugin", + "version": "1.0.7", + "description": "Rush plugin for upgrade rush.js in monorepo", + "keywords": [ + "rush", + "plugin", + "upgrade" + ], + "homepage": "https://github.com/tiktok/rush-plugins#readme", + "bugs": { + "url": "https://github.com/tiktok/rush-plugins/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tiktok/rush-plugins.git", + "directory": "rush-plugins/rush-upgrade-self-plugin" + }, + "license": "MIT", + "main": "lib/index.js", + "bin": { + "rush-upgrade-self": "lib/cli.js" + }, + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build --watch", + "prepublishOnly": "npm run build", + "test": "heft test" + }, + "dependencies": { + "@rushstack/node-core-library": "3.44.1", + "@rushstack/rush-sdk": "5.62.4", + "fast-glob": "~3.2.7", + "find-up": "5.0.0", + "inquirer": "~8.2.0", + "ora": "5.4.1", + "pacote": "~12.0.2" + }, + "devDependencies": { + "@rushstack/eslint-config": "2.4.5", + "@rushstack/heft": "0.43.2", + "@rushstack/heft-node-rig": "1.2.31", + "@types/heft-jest": "1.0.1", + "@types/inquirer": "~8.1.3", + "@types/node": "12.20.24", + "@types/pacote": "~11.1.1", + "eslint": "7.32.0", + "typescript": "4.4.2" + } +} diff --git a/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json b/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json new file mode 100644 index 0000000..452ef53 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/rush-plugin-manifest.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-upgrade-self-plugin", + "description": "Rush plugin for upgrade Rush itself", + "commandLineJsonFilePath": "command-line.json" + } + ] +} diff --git a/rush-plugins/rush-upgrade-self-plugin/src/cli.ts b/rush-plugins/rush-upgrade-self-plugin/src/cli.ts new file mode 100644 index 0000000..1477be3 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/src/cli.ts @@ -0,0 +1,20 @@ +#!/usr/bin/env node + +import { upgradeSelf } from "./upgrade-self"; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +main(); + +async function main(): Promise { + try { + await upgradeSelf(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + if (error.message) { + console.log(error.message); + } else { + throw error; + } + process.exit(1); + } +} diff --git a/rush-plugins/rush-upgrade-self-plugin/src/upgrade-self.ts b/rush-plugins/rush-upgrade-self-plugin/src/upgrade-self.ts new file mode 100644 index 0000000..0f0abb9 --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/src/upgrade-self.ts @@ -0,0 +1,188 @@ +import * as path from "path"; +import { + Colors, + Terminal, + ConsoleTerminalProvider, + JsonFile, + Executable, +} from "@rushstack/node-core-library"; +import { RushConfiguration } from "@rushstack/rush-sdk"; +import findUp from "find-up"; +import ora from "ora"; + +import type { Packument } from "pacote"; + +export const upgradeSelf = async (): Promise => { + const terminal: Terminal = new Terminal(new ConsoleTerminalProvider()); + + const rushJsonPath: string | undefined = await findUp("rush.json", { + cwd: process.cwd(), + }); + if (!rushJsonPath) { + throw new Error("Could not find rush.json"); + } + const monoRoot: string = path.dirname(rushJsonPath); + + const rushJson: any = JsonFile.load(rushJsonPath); + + const rushConfiguration: RushConfiguration = + RushConfiguration.loadFromDefaultLocation({ + startingFolder: process.cwd(), + }); + + if (!rushConfiguration) { + throw new Error("Unable to load rush configuration"); + } + + let versions: Packument["versions"] | undefined; + try { + const { packument } = await import("pacote"); + const info: Packument = await packument("@microsoft/rush", { + preferOnline: true, + }); + versions = info.versions; + } catch { + throw new Error("Failed to get versions of @microsoft/rush"); + } + + interface IAnswer { + version: string; + } + + const { prompt } = await import("inquirer"); + const answer: IAnswer = await prompt({ + type: "list", + name: "version", + message: "Pick up a target version", + choices: Object.keys(versions).reverse(), + }); + + const targetVersion: string = answer.version; + + let spinner: ora.Ora | undefined; + spinner = ora(`Updating rush.json with ${targetVersion}...`).start(); + + // const rushJsonPath: string = rushConfiguration.rushJsonFile; + // const monoRoot: string = rushConfiguration.rushJsonFolder; + const runRushJSPath: string = path.join( + rushConfiguration.commonScriptsFolder, + "install-run-rush.js" + ); + // const rushJson: any = JsonFile.load(rushJsonPath); + const oldVersion: string = rushJson.rushVersion; + + rushJson.rushVersion = targetVersion; + JsonFile.save(rushJson, rushJsonPath, { + updateExistingFile: true, + }); + + spinner.succeed(`Updated rush.json from ${oldVersion} to ${targetVersion}`); + + spinner = ora("Scanning for package.json files...").start(); + // eslint-disable-next-line @typescript-eslint/typedef + const fg = await import("fast-glob"); + + const allPackageJsonFiles: string[] = fg.sync(["**/package.json"], { + cwd: monoRoot, + ignore: ["node_modules/**", "**/node_modules/**", "**/temp/**"], + absolute: true, + }); + + spinner.succeed(`Found ${allPackageJsonFiles.length} package.json files`); + + spinner = ora( + "Updating Rush.js related dependencies in package.json files..." + ).start(); + + const depVersionMap: Record = { + "@rushstack/rush-sdk": targetVersion, + }; + for (const [k, v] of Object.entries( + versions[targetVersion]!.dependencies! + )) { + if (k.startsWith("@microsoft/") || k.startsWith("@rushstack/")) { + depVersionMap[k] = v; + } + } + + const changedPackageJsonFileSet: Set = new Set(); + for (const pkgJsonFile of allPackageJsonFiles) { + try { + const json: any = JsonFile.load(pkgJsonFile); + let changed: boolean = false; + for (const [pkgName, pkgVersion] of Object.entries(depVersionMap)) { + if (json.dependencies && json.dependencies[pkgName]) { + json.dependencies[pkgName] = pkgVersion; + changed = true; + } + if (json.devDependencies && json.devDependencies[pkgName]) { + json.devDependencies[pkgName] = pkgVersion; + changed = true; + } + } + if (changed) { + JsonFile.save(json, pkgJsonFile, { + onlyIfChanged: true, + }); + changedPackageJsonFileSet.add(pkgJsonFile); + terminal.writeVerboseLine(`${pkgJsonFile} updated`); + } + } catch { + terminal.writeWarningLine( + `${pkgJsonFile} is not a valid JSON file, ignored` + ); + } + } + + spinner.succeed( + `Updated ${changedPackageJsonFileSet.size} package.json files` + ); + + for (const packageJsonFile of changedPackageJsonFileSet) { + if (packageJsonFile.includes("common/autoinstallers")) { + const autoinstallerFolder: string = path.dirname(packageJsonFile); + const autoinstallerName: string = path.basename(autoinstallerFolder); + spinner = ora(`Updating autoinstaller ${autoinstallerName}`).start(); + try { + Executable.spawnSync("node", [ + runRushJSPath, + "update-autoinstaller", + "--name", + autoinstallerName, + ]); + } catch { + throw new Error(`Failed to update autoinstaller ${autoinstallerName}`); + } + spinner.succeed(`Updated autoinstaller ${autoinstallerName}`); + } + } + + interface IShouldRunRushUpdateAnswer { + shouldRunRushUpdate: boolean; + } + + const { shouldRunRushUpdate } = await prompt([ + { + type: "confirm", + name: "shouldRunRushUpdate", + message: "Run rush update right now?", + default: true, + }, + ]); + + if (shouldRunRushUpdate) { + terminal.writeLine("Run rush update..."); + try { + Executable.spawnSync("node", [runRushJSPath, "update"], { + stdio: "inherit", + }); + } catch (e) { + throw new Error("Failed to run rush update"); + } + terminal.writeLine("Rush update successfully."); + } else { + terminal.writeWarningLine("Rush update skipped, please run it manually."); + } + + terminal.writeLine(Colors.green("ALL DONE!")); +}; diff --git a/rush-plugins/rush-upgrade-self-plugin/tsconfig.json b/rush-plugins/rush-upgrade-self-plugin/tsconfig.json new file mode 100644 index 0000000..664294a --- /dev/null +++ b/rush-plugins/rush-upgrade-self-plugin/tsconfig.json @@ -0,0 +1,95 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "heft-jest", + "node" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + "declarationMap": true /* Create sourcemaps for d.ts files. */, + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./lib" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + "downlevelIteration": true /* Emit more compliant, but verbose and less performant JavaScript for iteration. */, + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/rush.json b/rush.json new file mode 100644 index 0000000..5a693a1 --- /dev/null +++ b/rush.json @@ -0,0 +1,501 @@ +/** + * This is the main configuration file for Rush. + * For full documentation, please see https://rushjs.io + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", + + /** + * (Required) This specifies the version of the Rush engine to be used in this repo. + * Rush's "version selector" feature ensures that the globally installed tool will + * behave like this release, regardless of which version is installed globally. + * + * The common/scripts/install-run-rush.js automation script also uses this version. + * + * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5" + * path segment in the "$schema" field for all your Rush config files. This will ensure + * correct error-underlining and tab-completion for editors such as VS Code. + */ + "rushVersion": "5.83.2", + + /** + * The next field selects which package manager should be installed and determines its version. + * Rush installs its own local copy of the package manager to ensure that your build process + * is fully isolated from whatever tools are present in the local environment. + * + * Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation + * for details about these alternatives. + */ + "pnpmVersion": "6.23.1", + + // "npmVersion": "6.14.15", + // "yarnVersion": "1.9.4", + + /** + * Options that are only used when the PNPM package manager is selected + */ + "pnpmOptions": { + /** + * Specifies the location of the PNPM store. There are two possible values: + * + * - "local" - use the "pnpm-store" folder in the current configured temp folder: + * "common/temp/pnpm-store" by default. + * - "global" - use PNPM's global store, which has the benefit of being shared + * across multiple repo folders, but the disadvantage of less isolation for builds + * (e.g. bugs or incompatibilities when two repos use different releases of PNPM) + * + * RUSH_PNPM_STORE_PATH will override the directory that will be used as the store + * + * In all cases, the store path will be overridden by the environment variable RUSH_PNPM_STORE_PATH. + * + * The default value is "local". + */ + // "pnpmStore": "local", + /** + * If true, then Rush will add the "--strict-peer-dependencies" option when invoking PNPM. + * This causes "rush install" to fail if there are unsatisfied peer dependencies, which is + * an invalid state that can cause build failures or incompatible dependency versions. + * (For historical reasons, JavaScript package managers generally do not treat this invalid + * state as an error.) + * + * The default value is false to avoid legacy compatibility issues. + * It is strongly recommended to set strictPeerDependencies=true. + */ + // "strictPeerDependencies": true, + /** + * Configures the strategy used to select versions during installation. + * + * This feature requires PNPM version 3.1 or newer. It corresponds to the "--resolution-strategy" command-line + * option for PNPM. Possible values are "fast" and "fewer-dependencies". PNPM's default is "fast", but this may + * be incompatible with certain packages, for example the "@types" packages from DefinitelyTyped. Rush's default + * is "fewer-dependencies", which causes PNPM to avoid installing a newer version if an already installed version + * can be reused; this is more similar to NPM's algorithm. + * + * After modifying this field, it's recommended to run "rush update --full" so that the package manager + * will recalculate all version selections. + */ + // "resolutionStrategy": "fast", + /** + * If true, then `rush install` will report an error if manual modifications + * were made to the PNPM shrinkwrap file without running "rush update" afterwards. + * + * This feature protects against accidental inconsistencies that may be introduced + * if the PNPM shrinkwrap file ("pnpm-lock.yaml") is manually edited. When this + * feature is enabled, "rush update" will append a hash to the file as a YAML comment, + * and then "rush update" and "rush install" will validate the hash. Note that this does not prohibit + * manual modifications, but merely requires "rush update" be run + * afterwards, ensuring that PNPM can report or repair any potential inconsistencies. + * + * To temporarily disable this validation when invoking "rush install", use the + * "--bypass-policy" command-line parameter. + * + * The default value is false. + */ + // "preventManualShrinkwrapChanges": true, + /** + * If true, then `rush install` will use the PNPM workspaces feature to perform the + * install. + * + * This feature uses PNPM to perform the entire monorepo install. When using workspaces, Rush will + * generate a "pnpm-workspace.yaml" file referencing all local projects to install. Rush will + * also generate a "pnpmfile.js" which is used to provide preferred versions support. When install + * is run, this pnpmfile will be used to replace dependency version ranges with a smaller subset + * of the original range. If the preferred version is not fully a subset of the original version + * range, it will be left as-is. After this, the pnpmfile.js provided in the repository (if one + * exists) will be called to further modify package dependencies. + * + * This option is experimental. The default value is false. + */ + "useWorkspaces": true + }, + + /** + * Older releases of the Node.js engine may be missing features required by your system. + * Other releases may have bugs. In particular, the "latest" version will not be a + * Long Term Support (LTS) version and is likely to have regressions. + * + * Specify a SemVer range to ensure developers use a Node.js version that is appropriate + * for your repo. + * + * LTS schedule: https://nodejs.org/en/about/releases/ + * LTS versions: https://nodejs.org/en/download/releases/ + */ + "nodeSupportedVersionRange": ">=12.13.0 <13.0.0 || >=14.15.0 <15.0.0 || >=16.13.0 <17.0.0", + + /** + * Odd-numbered major versions of Node.js are experimental. Even-numbered releases + * spend six months in a stabilization period before the first Long Term Support (LTS) version. + * For example, 8.9.0 was the first LTS version of Node.js 8. Pre-LTS versions are not recommended + * for production usage because they frequently have bugs. They may cause Rush itself + * to malfunction. + * + * Rush normally prints a warning if it detects a pre-LTS Node.js version. If you are testing + * pre-LTS versions in preparation for supporting the first LTS version, you can use this setting + * to disable Rush's warning. + */ + // "suppressNodeLtsWarning": false, + + /** + * If you would like the version specifiers for your dependencies to be consistent, then + * uncomment this line. This is effectively similar to running "rush check" before any + * of the following commands: + * + * rush install, rush update, rush link, rush version, rush publish + * + * In some cases you may want this turned on, but need to allow certain packages to use a different + * version. In those cases, you will need to add an entry to the "allowedAlternativeVersions" + * section of the common-versions.json. + */ + "ensureConsistentVersions": true, + + /** + * Large monorepos can become intimidating for newcomers if project folder paths don't follow + * a consistent and recognizable pattern. When the system allows nested folder trees, + * we've found that teams will often use subfolders to create islands that isolate + * their work from others ("shipping the org"). This hinders collaboration and code sharing. + * + * The Rush developers recommend a "category folder" model, where buildable project folders + * must always be exactly two levels below the repo root. The parent folder acts as the category. + * This provides a basic facility for grouping related projects (e.g. "apps", "libraries", + * "tools", "prototypes") while still encouraging teams to organize their projects into + * a unified taxonomy. Limiting to 2 levels seems very restrictive at first, but if you have + * 20 categories and 20 projects in each category, this scheme can easily accommodate hundreds + * of projects. In practice, you will find that the folder hierarchy needs to be rebalanced + * occasionally, but if that's painful, it's a warning sign that your development style may + * discourage refactoring. Reorganizing the categories should be an enlightening discussion + * that brings people together, and maybe also identifies poor coding practices (e.g. file + * references that reach into other project's folders without using Node.js module resolution). + * + * The defaults are projectFolderMinDepth=1 and projectFolderMaxDepth=2. + * + * To remove these restrictions, you could set projectFolderMinDepth=1 + * and set projectFolderMaxDepth to a large number. + */ + // "projectFolderMinDepth": 2, + // "projectFolderMaxDepth": 2, + + /** + * Today the npmjs.com registry enforces fairly strict naming rules for packages, but in the early + * days there was no standard and hardly any enforcement. A few large legacy projects are still using + * nonstandard package names, and private registries sometimes allow it. Set "allowMostlyStandardPackageNames" + * to true to relax Rush's enforcement of package names. This allows upper case letters and in the future may + * relax other rules, however we want to minimize these exceptions. Many popular tools use certain punctuation + * characters as delimiters, based on the assumption that they will never appear in a package name; thus if we relax + * the rules too much it is likely to cause very confusing malfunctions. + * + * The default value is false. + */ + // "allowMostlyStandardPackageNames": true, + + /** + * This feature helps you to review and approve new packages before they are introduced + * to your monorepo. For example, you may be concerned about licensing, code quality, + * performance, or simply accumulating too many libraries with overlapping functionality. + * The approvals are tracked in two config files "browser-approved-packages.json" + * and "nonbrowser-approved-packages.json". See the Rush documentation for details. + */ + // "approvedPackagesPolicy": { + // /** + // * The review categories allow you to say for example "This library is approved for usage + // * in prototypes, but not in production code." + // * + // * Each project can be associated with one review category, by assigning the "reviewCategory" field + // * in the "projects" section of rush.json. The approval is then recorded in the files + // * "common/config/rush/browser-approved-packages.json" and "nonbrowser-approved-packages.json" + // * which are automatically generated during "rush update". + // * + // * Designate categories with whatever granularity is appropriate for your review process, + // * or you could just have a single category called "default". + // */ + // "reviewCategories": [ + // // Some example categories: + // "production", // projects that ship to production + // "tools", // non-shipping projects that are part of the developer toolchain + // "prototypes" // experiments that should mostly be ignored by the review process + // ], + // + // /** + // * A list of NPM package scopes that will be excluded from review. + // * We recommend to exclude TypeScript typings (the "@types" scope), because + // * if the underlying package was already approved, this would imply that the typings + // * are also approved. + // */ + // // "ignoredNpmScopes": ["@types"] + // }, + + /** + * If you use Git as your version control system, this section has some additional + * optional features you can use. + */ + "gitPolicy": { + /** + * Work at a big company? Tired of finding Git commits at work with unprofessional Git + * emails such as "beer-lover@my-college.edu"? Rush can validate people's Git email address + * before they get started. + * + * Define a list of regular expressions describing allowable e-mail patterns for Git commits. + * They are case-insensitive anchored JavaScript RegExps. Example: ".*@example\.com" + * + * IMPORTANT: Because these are regular expressions encoded as JSON string literals, + * RegExp escapes need two backslashes, and ordinary periods should be "\\.". + */ + "allowedEmailRegExps": [ + "[^@]+@users\\.noreply\\.github\\.com" + // "travis@example\\.org" + ], + /** + * When Rush reports that the address is malformed, the notice can include an example + * of a recommended email. Make sure it conforms to one of the allowedEmailRegExps + * expressions. + */ + "sampleEmail": "mrexample@users.noreply.github.com" + /** + * The commit message to use when committing changes during 'rush publish'. + * + * For example, if you want to prevent these commits from triggering a CI build, + * you might configure your system's trigger to look for a special string such as "[skip-ci]" + * in the commit message, and then customize Rush's message to contain that string. + */ + // "versionBumpCommitMessage": "Bump versions [skip ci]", + /** + * The commit message to use when committing changes during 'rush version'. + * + * For example, if you want to prevent these commits from triggering a CI build, + * you might configure your system's trigger to look for a special string such as "[skip-ci]" + * in the commit message, and then customize Rush's message to contain that string. + */ + // "changeLogUpdateCommitMessage": "Update changelogs [skip ci]" + }, + + "repository": { + /** + * The URL of this Git repository, used by "rush change" to determine the base branch for your PR. + * + * The "rush change" command needs to determine which files are affected by your PR diff. + * If you merged or cherry-picked commits from the master branch into your PR branch, those commits + * should be excluded from this diff (since they belong to some other PR). In order to do that, + * Rush needs to know where to find the base branch for your PR. This information cannot be + * determined from Git alone, since the "pull request" feature is not a Git concept. Ideally + * Rush would use a vendor-specific protocol to query the information from GitHub, Azure DevOps, etc. + * But to keep things simple, "rush change" simply assumes that your PR is against the "master" branch + * of the Git remote indicated by the repository.url setting in rush.json. If you are working in + * a GitHub "fork" of the real repo, this setting will be different from the repository URL of your + * your PR branch, and in this situation "rush change" will also automatically invoke "git fetch" + * to retrieve the latest activity for the remote master branch. + */ + "url": "https://github.com/tiktok/rush-plugins", + /** + * The default branch name. This tells "rush change" which remote branch to compare against. + * The default value is "master" + */ + "defaultBranch": "main", + /** + * The default remote. This tells "rush change" which remote to compare against if the remote URL is + * not set or if a remote matching the provided remote URL is not found. + */ + "defaultRemote": "origin" + }, + + /** + * Event hooks are customized script actions that Rush executes when specific events occur + */ + "eventHooks": { + /** + * The list of shell commands to run before the Rush installation starts + */ + "preRushInstall": [ + // "common/scripts/pre-rush-install.js" + ], + + /** + * The list of shell commands to run after the Rush installation finishes + */ + "postRushInstall": [ + "node common/scripts/install-run-rush.js sort-package-json" + ], + + /** + * The list of shell commands to run before the Rush build command starts + */ + "preRushBuild": [], + + /** + * The list of shell commands to run after the Rush build command finishes + */ + "postRushBuild": [] + }, + + /** + * Installation variants allow you to maintain a parallel set of configuration files that can be + * used to build the entire monorepo with an alternate set of dependencies. For example, suppose + * you upgrade all your projects to use a new release of an important framework, but during a transition period + * you intend to maintain compatibility with the old release. In this situation, you probably want your + * CI validation to build the entire repo twice: once with the old release, and once with the new release. + * + * Rush "installation variants" correspond to sets of config files located under this folder: + * + * common/config/rush/variants/ + * + * The variant folder can contain an alternate common-versions.json file. Its "preferredVersions" field can be used + * to select older versions of dependencies (within a loose SemVer range specified in your package.json files). + * To install a variant, run "rush install --variant ". + * + * For more details and instructions, see this article: https://rushjs.io/pages/advanced/installation_variants/ + */ + "variants": [ + // { + // /** + // * The folder name for this variant. + // */ + // "variantName": "old-sdk", + // + // /** + // * An informative description + // */ + // "description": "Build this repo using the previous release of the SDK" + // } + ], + + /** + * Rush can collect anonymous telemetry about everyday developer activity such as + * success/failure of installs, builds, and other operations. You can use this to identify + * problems with your toolchain or Rush itself. THIS TELEMETRY IS NOT SHARED WITH MICROSOFT. + * It is written into JSON files in the common/temp folder. It's up to you to write scripts + * that read these JSON files and do something with them. These scripts are typically registered + * in the "eventHooks" section. + */ + // "telemetryEnabled": false, + + /** + * Allows creation of hotfix changes. This feature is experimental so it is disabled by default. + * If this is set, 'rush change' only allows a 'hotfix' change type to be specified. This change type + * will be used when publishing subsequent changes from the monorepo. + */ + // "hotfixChangeEnabled": false, + + /** + * (Required) This is the inventory of projects to be managed by Rush. + * + * Rush does not automatically scan for projects using wildcards, for a few reasons: + * 1. Depth-first scans are expensive, particularly when tools need to repeatedly collect the list. + * 2. On a caching CI machine, scans can accidentally pick up files left behind from a previous build. + * 3. It's useful to have a centralized inventory of all projects and their important metadata. + */ + "projects": [ + // { + // /** + // * The NPM package name of the project (must match package.json) + // */ + // "packageName": "my-app", + // + // /** + // * The path to the project folder, relative to the rush.json config file. + // */ + // "projectFolder": "apps/my-app", + // + // /** + // * An optional category for usage in the "browser-approved-packages.json" + // * and "nonbrowser-approved-packages.json" files. The value must be one of the + // * strings from the "reviewCategories" defined above. + // */ + // "reviewCategory": "production", + // + // /** + // * A list of local projects that appear as devDependencies for this project, but cannot be + // * locally linked because it would create a cyclic dependency; instead, the last published + // * version will be installed in the Common folder. + // */ + // "cyclicDependencyProjects": [ + // // "my-toolchain" + // ], + // + // /** + // * If true, then this project will be ignored by the "rush check" command. + // * The default value is false. + // */ + // // "skipRushCheck": false, + // + // /** + // * A flag indicating that changes to this project will be published to npm, which affects + // * the Rush change and publish workflows. The default value is false. + // * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both. + // */ + // // "shouldPublish": false, + // + // /** + // * Facilitates postprocessing of a project's files prior to publishing. + // * + // * If specified, the "publishFolder" is the relative path to a subfolder of the project folder. + // * The "rush publish" command will publish the subfolder instead of the project folder. The subfolder + // * must contain its own package.json file, which is typically a build output. + // */ + // // "publishFolder": "temp/publish", + // + // /** + // * An optional version policy associated with the project. Version policies are defined + // * in "version-policies.json" file. See the "rush publish" documentation for more info. + // * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both. + // */ + // // "versionPolicyName": "" + // }, + // + // { + // "packageName": "my-controls", + // "projectFolder": "libraries/my-controls", + // "reviewCategory": "production" + // }, + // + // { + // "packageName": "my-toolchain", + // "projectFolder": "tools/my-toolchain", + // "reviewCategory": "tools" + // } + { + "packageName": "rush-init-project-plugin", + "projectFolder": "rush-plugins/rush-init-project-plugin", + "reviewCategory": "rush-plugins", + "shouldPublish": true + }, + { + "packageName": "rush-archive-project-plugin", + "projectFolder": "rush-plugins/rush-archive-project-plugin", + "reviewCategory": "rush-plugins", + "shouldPublish": true + }, + { + "packageName": "rush-upgrade-self-plugin", + "projectFolder": "rush-plugins/rush-upgrade-self-plugin", + "reviewCategory": "rush-plugins", + "shouldPublish": true + }, + { + "packageName": "rush-sort-package-json", + "projectFolder": "rush-plugins/rush-sort-package-json", + "reviewCategory": "rush-plugins", + "shouldPublish": true + }, + { + "packageName": "rush-print-log-if-error-plugin", + "projectFolder": "rush-plugins/rush-print-log-if-error-plugin", + "reviewCategory": "rush-plugins", + "shouldPublish": true, + "cyclicDependencyProjects": [] + }, + { + "packageName": "rush-lint-staged-plugin", + "projectFolder": "rush-plugins/rush-lint-staged-plugin", + "shouldPublish": true, + "cyclicDependencyProjects": [] + }, + { + "packageName": "rush-audit-cache-plugin", + "projectFolder": "rush-plugins/rush-audit-cache-plugin", + "shouldPublish": true + }, + { + "packageName": "rush-git-lfs-plugin", + "projectFolder": "rush-plugins/rush-git-lfs-plugin", + "shouldPublish": true + } + ] +}