From 25b17bc0b85615bc81ce21469d499a4abe2284d8 Mon Sep 17 00:00:00 2001 From: Michiel Pauw Date: Thu, 21 Nov 2024 14:33:09 +0100 Subject: [PATCH] chore: clean branch --- package-lock.json | 1038 +++++++++++++---- packages-node/migrate-cli/CHANGELOG.md | 15 + packages-node/migrate-cli/README.md | 123 ++ packages-node/migrate-cli/index.js | 4 + packages-node/migrate-cli/package.json | 58 + packages-node/migrate-cli/src/MigrateCli.js | 180 +++ .../src/cli-helpers/AsyncEventEmitter.js | 21 + .../migrate-cli/src/cli-helpers/mergeDeep.js | 30 + packages-node/migrate-cli/src/cli.js | 25 + .../src/commands/UpgradeCommandBase.js | 340 ++++++ .../executeJsCodeShiftTransforms.js | 220 ++++ .../migrate-helpers/getJsBlocksFromMdFiles.js | 126 ++ .../src/migrate-helpers/verifyPackageJson.js | 89 ++ .../migrate-cli/test-helpers/.gitignore | 1 + .../migrate-cli/test-helpers/mock-helpers.js | 34 + .../migrate-cli/test-helpers/pretty-format.js | 57 + .../migrate-cli/test-helpers/test-helpers.js | 303 +++++ .../migrate-cli/test-helpers/types.ts | 26 + .../migrate-cli/test/CLI/MigrateCli.test.js | 63 + .../migrate-cli/test/CLI/cli.test.js | 318 +++++ .../test/commands/UpgradeCommandBase.test.js | 163 +++ .../executeJsCodeShiftTransforms.test.js | 233 ++++ .../src/another.js | 1 + .../src/index.js | 1 + .../transforms/write_-_cjs-export.cjs | 3 + .../test/mocks/commands/MockCommand.js | 15 + .../migrate-cli/test/mocks/config-file-1.js | 4 + packages-node/migrate-cli/tsconfig.json | 9 + packages-node/migrate-cli/types/index.ts | 39 + ...roject_0.0.2-target-mock__-1281497701.json | 220 ++++ ...-project_0.0.2-target-mock__983214811.json | 52 + ...porting-ref-project_1.0.0__-882566805.json | 194 +++ ...-project_0.0.2-target-mock__728837360.json | 204 ++++ ...xporting-ref-project_1.0.0__-18301594.json | 162 +++ ...orting-ref-project_1.0.0__-1531951975.json | 94 ++ ...xporting-ref-project_1.0.0__119660402.json | 67 ++ scripts/lint-versions.js | 4 + 37 files changed, 4283 insertions(+), 253 deletions(-) create mode 100644 packages-node/migrate-cli/CHANGELOG.md create mode 100644 packages-node/migrate-cli/README.md create mode 100644 packages-node/migrate-cli/index.js create mode 100644 packages-node/migrate-cli/package.json create mode 100644 packages-node/migrate-cli/src/MigrateCli.js create mode 100644 packages-node/migrate-cli/src/cli-helpers/AsyncEventEmitter.js create mode 100644 packages-node/migrate-cli/src/cli-helpers/mergeDeep.js create mode 100755 packages-node/migrate-cli/src/cli.js create mode 100644 packages-node/migrate-cli/src/commands/UpgradeCommandBase.js create mode 100644 packages-node/migrate-cli/src/migrate-helpers/executeJsCodeShiftTransforms.js create mode 100644 packages-node/migrate-cli/src/migrate-helpers/getJsBlocksFromMdFiles.js create mode 100644 packages-node/migrate-cli/src/migrate-helpers/verifyPackageJson.js create mode 100644 packages-node/migrate-cli/test-helpers/.gitignore create mode 100644 packages-node/migrate-cli/test-helpers/mock-helpers.js create mode 100644 packages-node/migrate-cli/test-helpers/pretty-format.js create mode 100644 packages-node/migrate-cli/test-helpers/test-helpers.js create mode 100644 packages-node/migrate-cli/test-helpers/types.ts create mode 100644 packages-node/migrate-cli/test/CLI/MigrateCli.test.js create mode 100644 packages-node/migrate-cli/test/CLI/cli.test.js create mode 100644 packages-node/migrate-cli/test/commands/UpgradeCommandBase.test.js create mode 100644 packages-node/migrate-cli/test/migrate-helpers/executeJsCodeShiftTransforms.test.js create mode 100644 packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/another.js create mode 100644 packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/index.js create mode 100644 packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/transforms/write_-_cjs-export.cjs create mode 100644 packages-node/migrate-cli/test/mocks/commands/MockCommand.js create mode 100644 packages-node/migrate-cli/test/mocks/config-file-1.js create mode 100644 packages-node/migrate-cli/tsconfig.json create mode 100644 packages-node/migrate-cli/types/index.ts create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/find-classes_-_importing-target-project_0.0.2-target-mock__-1281497701.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/find-customelements_-_importing-target-project_0.0.2-target-mock__983214811.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/find-exports_-_exporting-ref-project_1.0.0__-882566805.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/find-imports_-_importing-target-project_0.0.2-target-mock__728837360.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/match-imports_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-18301594.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/match-paths_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-1531951975.json create mode 100644 packages-node/providence-analytics/test-node/program/analyzers/e2e/match-subclasses_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__119660402.json diff --git a/package-lock.json b/package-lock.json index d2dc292225..b0fd20dd20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -308,12 +308,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", - "license": "MIT", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -398,12 +398,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", - "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", - "license": "MIT", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -413,13 +413,11 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", - "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -429,7 +427,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.7", @@ -465,18 +463,16 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", - "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.7", - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/helper-replace-supers": "^7.25.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", - "@babel/traverse": "^7.25.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "engines": { @@ -490,7 +486,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -500,7 +495,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -518,7 +513,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -528,7 +523,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -542,42 +537,37 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", - "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", - "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", - "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -587,23 +577,20 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", - "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", - "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "engines": { "node": ">=6.9.0" } @@ -612,7 +599,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -627,15 +614,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", - "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.7", - "@babel/helper-optimise-call-expression": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -645,55 +630,49 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", - "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", - "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", - "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "engines": { "node": ">=6.9.0" } @@ -702,7 +681,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.7", @@ -726,28 +705,12 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", - "license": "MIT", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -760,7 +723,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -777,7 +740,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -793,7 +756,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -809,7 +772,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -827,7 +790,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -862,7 +825,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -897,6 +860,20 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", @@ -916,7 +893,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -941,6 +918,20 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", @@ -954,11 +945,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -975,7 +980,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -991,7 +996,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.8.tgz", "integrity": "sha512-9ypqkozyzpG+HxlH4o4gdctalFGIjjdufzo7I2XPda0iBnZ6a+FO0rIEQcdSPXp02CkvGsII1exJhmROPQd5oA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1009,7 +1014,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.7", @@ -1027,7 +1032,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1043,7 +1048,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1059,7 +1064,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -1076,7 +1080,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz", "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -1093,7 +1097,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -1114,7 +1118,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1131,7 +1135,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1147,7 +1151,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1164,7 +1168,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1180,7 +1184,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1197,7 +1201,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz", "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1213,7 +1217,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", @@ -1230,7 +1234,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz", "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1242,11 +1246,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", + "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-flow": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1263,7 +1282,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.7", @@ -1281,7 +1300,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz", "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1297,7 +1316,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1313,7 +1332,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz", "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1329,7 +1348,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1345,7 +1364,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -1359,15 +1378,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", - "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", - "dev": true, - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", "dependencies": { - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helper-plugin-utils": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1380,7 +1397,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -1399,7 +1416,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.7", @@ -1416,7 +1433,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1433,7 +1450,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1449,7 +1466,6 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz", "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1465,7 +1481,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz", "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1481,7 +1497,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz", "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.7", @@ -1499,7 +1515,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1516,7 +1532,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz", "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1532,7 +1548,6 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz", "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1549,7 +1564,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1565,7 +1580,6 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.7", @@ -1582,7 +1596,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz", "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.7", @@ -1600,7 +1614,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1616,7 +1630,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1633,7 +1647,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1680,7 +1694,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1696,7 +1710,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7", @@ -1713,7 +1727,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1729,7 +1743,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1745,7 +1759,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1757,11 +1771,29 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.7" @@ -1777,7 +1809,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1794,7 +1826,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1811,7 +1843,7 @@ "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.7", @@ -1828,7 +1860,7 @@ "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.8.tgz", "integrity": "sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.25.8", @@ -1911,17 +1943,33 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/@babel/preset-flow": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", + "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1932,11 +1980,75 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", + "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@babel/runtime": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -1946,30 +2058,28 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", - "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1978,14 +2088,12 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -6412,6 +6520,28 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jscodeshift": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.11.tgz", + "integrity": "sha512-d7CAfFGOupj5qCDqMODXxNz2/NwCv/Lha78ZFbnr6qpk3K98iSB8I+ig9ERE2+EeYML352VMRsjPyOpeA+04eQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.14.1", + "recast": "^0.20.3" + } + }, + "node_modules/@types/jscodeshift/node_modules/ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -6555,6 +6685,12 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -8401,6 +8537,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -8862,7 +8999,7 @@ "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", @@ -8877,7 +9014,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8887,7 +9024,7 @@ "version": "0.10.6", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -8901,7 +9038,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" @@ -9561,7 +9698,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, "license": "MIT" }, "node_modules/builtin-modules": { @@ -9903,6 +10039,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -10512,6 +10649,19 @@ "node": ">=0.8" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -10558,6 +10708,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -10574,6 +10725,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, "license": "MIT" }, "node_modules/color-string": { @@ -10715,6 +10867,11 @@ "node": ">=4.0.0" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, "node_modules/compress-commons": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", @@ -10932,7 +11089,7 @@ "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "browserslist": "^4.23.3" @@ -12275,6 +12432,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -13010,7 +13168,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -13086,7 +13243,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -13474,6 +13631,47 @@ "dev": true, "license": "MIT" }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", @@ -13542,6 +13740,14 @@ "dev": true, "license": "ISC" }, + "node_modules/flow-parser": { + "version": "0.254.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.254.0.tgz", + "integrity": "sha512-FhO64nGWlkrCxMWRDL1Wbok+ep4iSw2t6EtuyYOFZRzBh902iynZ/GMDU/3RSbiKTmALkcmCmKQLe0eOWdMA8Q==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -14422,6 +14628,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -15171,7 +15378,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -15747,6 +15953,17 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -16007,6 +16224,14 @@ "dev": true, "license": "ISC" }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -16352,8 +16577,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -16376,6 +16600,87 @@ "dev": true, "license": "MIT" }, + "node_modules/jscodeshift": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.1.1.tgz", + "integrity": "sha512-4vq5B1sD37aa9qed3zWq2XQPun5XjxebIv+Folr57lt8B4HLGDHEz1UG7pfcxzSaelzPbcY7yZSs033/S0i6wQ==", + "dependencies": { + "@babel/core": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@babel/register": "^7.24.6", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.7", + "neo-async": "^2.5.0", + "picocolors": "^1.0.1", + "recast": "^0.23.9", + "tmp": "^0.2.3", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jscodeshift/node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jscodeshift/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jscodeshift/node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "engines": { + "node": ">=14.14" + } + }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -16606,7 +16911,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -17655,7 +17959,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/lodash.get": { @@ -19385,6 +19689,10 @@ "node": ">=8.6" } }, + "node_modules/migrate-cli": { + "resolved": "packages-node/migrate-cli", + "link": true + }, "node_modules/mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", @@ -19870,6 +20178,37 @@ "node": ">=12.0.0" } }, + "node_modules/mock-require": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", + "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", + "dev": true, + "dependencies": { + "get-caller-file": "^1.0.2", + "normalize-path": "^2.1.1" + }, + "engines": { + "node": ">=4.3.0" + } + }, + "node_modules/mock-require/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/mock-require/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", @@ -20008,7 +20347,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, "license": "MIT" }, "node_modules/nested-error-stacks": { @@ -20738,7 +21076,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -20807,7 +21144,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -21451,6 +21787,67 @@ "node": ">=4" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/playwright": { "version": "1.48.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0.tgz", @@ -22020,6 +22417,26 @@ "asap": "~2.0.3" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -22766,6 +23183,42 @@ "node": ">=8.10.0" } }, + "node_modules/recast": { + "version": "0.20.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", + "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "dev": true, + "dependencies": { + "ast-types": "0.14.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/recursive-copy": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.14.tgz", @@ -22845,14 +23298,14 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -22865,14 +23318,14 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" @@ -22901,7 +23354,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", @@ -22919,14 +23372,14 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -23560,6 +24013,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -24565,6 +25024,17 @@ "dev": true, "license": "MIT" }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/sharp": { "version": "0.29.3", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.29.3.tgz", @@ -24823,6 +25293,11 @@ "node": ">=8" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -25050,7 +25525,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -25061,7 +25535,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -25628,6 +26101,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -25915,6 +26389,11 @@ "node": ">=0.8.0" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -25928,15 +26407,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -26016,7 +26486,6 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", - "dev": true, "license": "0BSD" }, "node_modules/tsscmp": { @@ -26303,7 +26772,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=4" @@ -26313,7 +26782,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", @@ -26327,7 +26796,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=4" @@ -26337,7 +26806,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=4" @@ -28062,6 +28531,29 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -28316,6 +28808,46 @@ "version": "0.5.3", "license": "MIT" }, + "packages-node/migrate-cli": { + "version": "0.1.0", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "globby": "^14.0.2", + "jscodeshift": "^17.1.1", + "prompts": "^2.4.2", + "providence-analytics": "^0.17.0", + "semver": "^7.6.3" + }, + "bin": { + "migrate-cli": "src/cli.js" + }, + "devDependencies": { + "@types/jscodeshift": "^0.11.11", + "@types/semver": "^7.5.8", + "chai-as-promised": "^8.0.0", + "mock-require": "^3.0.3" + } + }, + "packages-node/migrate-cli/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "packages-node/migrate-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, "packages-node/nodejs-helpers": { "name": "@lion/nodejs-helpers", "version": "0.1.0", @@ -28337,7 +28869,7 @@ "license": "MIT" }, "packages-node/providence-analytics": { - "version": "0.17.0", + "version": "0.17.2", "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.7", @@ -28587,7 +29119,7 @@ }, "packages/ajax": { "name": "@lion/ajax", - "version": "2.0.2", + "version": "2.1.0", "license": "MIT" }, "packages/singleton-manager": { @@ -28596,7 +29128,7 @@ }, "packages/ui": { "name": "@lion/ui", - "version": "0.8.3", + "version": "0.8.6", "license": "MIT", "dependencies": { "@bundled-es-modules/message-format": "^6.2.4", diff --git a/packages-node/migrate-cli/CHANGELOG.md b/packages-node/migrate-cli/CHANGELOG.md new file mode 100644 index 0000000000..9362ad38be --- /dev/null +++ b/packages-node/migrate-cli/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog `migrate-cli` +All notable changes to this project will be documented in this file. + +## 0.1.0 - 2024-10-29 + +### Initial commit + +- feat: added `cli` to run migrations +- feat: export `MigrateCli`: class using `Commander` to provide a intuitive and adaptable CLI +- feat: export `UpgradeCommandBase`: extendable command implementing upgrade behaviour +- feat: export `executeJsCodeShiftTransforms`: function that runs `jscodeshift` on a codebase +- test: added unit tests for classes +- test: WIP e2e testing of CLI +- test: WIP unit tests for `executeJsCodeShiftTransforms` +- chore: added README diff --git a/packages-node/migrate-cli/README.md b/packages-node/migrate-cli/README.md new file mode 100644 index 0000000000..e9bc6040ec --- /dev/null +++ b/packages-node/migrate-cli/README.md @@ -0,0 +1,123 @@ +# migrate-cli + +## What? + +The `migrate-cli` provides a more or less plug and play solution for running codemods / code transforms using (by default) JSCodeshift. + +## For whom? + +The CLI is aimed at platform developers that want to make migrations easy for their users. Using this CLI, they can focus on writing high quality code transforms, without worrying about the overhead that comes with managing a CLI. + +## How? + +```bash +npx migrate-cli +npx migrate-cli upgrade --help +npx migrate-cli upgrade -t lib-foo-1-to-2 -u /path/to/upgrades/dir +``` + +### Migration tasks + +To use this CLI, you need one or more 'migration tasks'. These tasks are intended to perform a (part of a) migration on a certain codebase. A task can perform actions on single files (like updating a `package.json`), but are best used to perform actions on many files (rewriting of imports in all relevant `.js` files, change of API, etc.). + +The CLI expects migration tasks to be in the following structure: + +```bash +├── lib-foo-2-to-3 + ├── index.js + └── jscodeshift + ├── 01-some-api-transform.js + ├── 01-some-api-transform*-\_cjs-export.cjs + ├── 02-some-code-removal-transform.js + ├── 02-some-code-removal-transform*-_cjs-export.cjs + ├── 03-import-transform.js + ├── 03-import-transform_-\_cjs-export.cjs +``` + +### `index.js` + +Here `index.js` is the entry point to the migration task, and it must have a function with the following signature: + +```javascript +export async function upgrade(jscsOpts, workspaceMeta) { + ... +} +``` + +`jscsOpts` by default contains minimal information required for running the CLI. More options can be added by enriching the `jscsOpts` object in the CLI configuration. + +`workspaceMeta` contains information that is relevant when running the CLI in a monorepo. + +#### `executeJsCodeShiftTransforms` + +The function `executeJsCodeShiftTransforms` is exported by this project. Its signature is as follows: + +```javascript +export async function executeJsCodeShiftTransforms( + inputDir, + transformsFolder, + jscsOptions = {}, +) +``` + +This function can be called from `index.js` to perform the transformations in `transformsFolder` (`jscodeshift` in the example above) against a codebase found in `inputDir`. By default, this function will also be passed in the `jscsOpts` as `transformFunction`, so that it does not need to be imported. + +### Basic usage + +With this structure in mind, a minimal implementation of the CLI can be used by running the following command in the root of a codebase: + +```bash +npx migrate-cli upgrade -t lib-foo-2-to-3 -u /path/or/url/to/parent-dir/ +``` + +When this is run, the following things will happen: + +- The CLI will look in the provided directory for a directory called `lib-foo-2-to-3`; +- If found, it will call the `upgrade` function in `index.js`; + +#### Configuration + +By default, the CLI will look for a `migrate-cli.config.(m)js` in the folder where it is run. You can also provide a config file using the `-c` option of the `upgrade` command. + +The most common configurable properties are listed below: + +| Property | Description | +| -------------------- | -------------------------------------------------------------------------------- | +| `inputDir` | Root directory of the project to be migrated | +| `task` | Upgrade task that should be performed | +| `jscsOpts` | Options object passed to `index.js` of the upgrade | +| `upgradesDir` | URL or string providing the directory where one or more upgrades can be found | +| `upgradesConfigHref` | Upgrade specific configuration (defaults to `${upgradesDir}/upgrades.config.js`) | +| `upgradeTaskUrl` | Location of a specific upgrade task | + +The upgrade command always needs to resolve to a specific task. Therefore, it will always require either a `task` and an `upgradesDir`, or an `upgradesTaskUrl`. + +### Advanced usage + +A user can also implement the CLI in their own project, allowing for more advanced functionality. A user can enhance the CLI in the following ways: + +1. By initializing the `MigrateCli` passing an `initOptions` object (allowing for additional commands, changing name and introduction text, etc.); +2. By extending the `UpgradeCommandBase` class to suit their specific needs. + +#### Example of initializing with initial options + +An example implementation of (1): + +```javascript +import { MigrateCli } from './MigrateCli.js'; +import path from 'path'; + +const initOptions = { + cliOptions: { + upgradesUrl: new URL('./upgrades', import.meta.url), // will look for potential upgrades in this directory + }, + commandsUrls: [new URL('./commands', import.meta.url)], // allows for more (or more specific) commands to be loaded from this directory + includeBaseCommands: false, // if true, UpgradeBaseCommand will be included as well as user specified commands + cliIntroductionText: `Welcome to lib-foo-migrate CLI 👋\n`, + pathToPkgJson: path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), // specify so version can be retrieved +}; + +const cli = new MigrateCli(initOptions); + +cli.start(); +``` diff --git a/packages-node/migrate-cli/index.js b/packages-node/migrate-cli/index.js new file mode 100644 index 0000000000..0a70cff350 --- /dev/null +++ b/packages-node/migrate-cli/index.js @@ -0,0 +1,4 @@ +export { MigrateCli } from './src/MigrateCli.js'; +export { UpgradeCommandBase } from './src/commands/UpgradeCommandBase.js'; + +export { executeJsCodeShiftTransforms } from './src/migrate-helpers/executeJsCodeShiftTransforms.js'; diff --git a/packages-node/migrate-cli/package.json b/packages-node/migrate-cli/package.json new file mode 100644 index 0000000000..af7ab84d5a --- /dev/null +++ b/packages-node/migrate-cli/package.json @@ -0,0 +1,58 @@ +{ + "name": "migrate-cli", + "version": "0.1.0", + "description": "CLI to execute migration with custom transforms", + "author": "ing-bank", + "repository": { + "type": "git", + "url": "https://github.com/ing-bank/lion.git", + "directory": "packages-node/migrate-cli" + }, + "type": "module", + "exports": { + ".": "./index.js" + }, + "bin": { + "migrate-cli": "src/cli.js" + }, + "scripts": { + "lint": "eslint . && prettier \"**/*.js\" --check --ignore-path .lintignore", + "test": "mocha test/**/*.test.js --timeout 8000", + "types": "wireit" + }, + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "globby": "^14.0.2", + "jscodeshift": "^17.1.1", + "prompts": "^2.4.2", + "providence-analytics": "^0.17.0", + "semver": "^7.6.3" + }, + "devDependencies": { + "@types/jscodeshift": "^0.11.11", + "@types/semver": "^7.5.8", + "chai-as-promised": "^8.0.0", + "mock-require": "^3.0.3" + }, + "keywords": [ + "cli", + "codemod", + "jscodeshift", + "migrate" + ], + "wireit": { + "types": { + "command": "tsc --build --pretty", + "files": [ + "src", + "test-node", + "types", + "tsconfig.json" + ], + "output": [ + "dist-types/**" + ] + } + } +} diff --git a/packages-node/migrate-cli/src/MigrateCli.js b/packages-node/migrate-cli/src/MigrateCli.js new file mode 100644 index 0000000000..8d99a4217f --- /dev/null +++ b/packages-node/migrate-cli/src/MigrateCli.js @@ -0,0 +1,180 @@ +/* eslint-disable new-cap, no-await-in-loop, no-console */ +import { Command } from 'commander'; +import path, { dirname } from 'path'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; + +import { mergeDeep } from './cli-helpers/mergeDeep.js'; +import { AsyncEventEmitter } from './cli-helpers/AsyncEventEmitter.js'; + +/** + * @typedef {{ plugins: {setupCommand:function;stop:function}[]; argv:string[];commandsUrls:URL[]}} Config + * @typedef {import('../types/index.js').Options}Options + * @typedef {import('../types/index.js').InitOptions}InitOptions + */ + +export class MigrateCli { + /** @type {Options} */ + options = { + // Codemod options + configFile: '', + inputDir: 'FALLBACK', + cwd: process.cwd(), + jscsOpts: {}, + upgradeTaskUrl: '', + upgradesDir: '', + _upgradesDirUrl: undefined, + upgradeTaskNames: [], + }; + + events = new AsyncEventEmitter(); + + /** @type {{setupCommand: function; upgrade?:function; runDoctorTask?:function}|undefined} */ + activePlugin = undefined; + + /** + * @param {InitOptions} initOptions + */ + constructor(initOptions = {}) { + /** @type {Config} */ + this.config = { + argv: initOptions.argv || process.argv, + commandsUrls: initOptions.commandsUrls || [], + plugins: initOptions.plugins || [], + }; + + if (!this.config.commandsUrls.length || initOptions.includeBaseCommands) { + this.config.commandsUrls.push(new URL('./commands', import.meta.url)); + } + this.program = new Command(); + // TODO: for later find a way to accept a config file without overriding the build in help + // this.program.allowUnknownOption().option('-c, --config-file ', 'path to config file'); + // this.program.parse(this.config.argv); + + this.program.allowUnknownOption(false); + this.program.addHelpText( + 'before', + initOptions.cliIntroductionText || `Welcome to the migrate CLI 👋\n`, + ); + this.pathToPkgJson = + initOptions.pathToPkgJson || + path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'); + + if (initOptions.options) { + this.setOptions(initOptions.options); + } + + const { name, version } = this.getNameAndVersion(); + this.program.version(initOptions.cliVersion || version, '-v, --version'); + this.program.name = () => name; + if (this.program.opts().configFile) { + this.options.configFile = this.program.opts().configFile; + } + } + + getNameAndVersion() { + try { + const pkgJsonContents = JSON.parse(fs.readFileSync(this.pathToPkgJson, 'utf8')); + return { + version: pkgJsonContents.version || 'N/A', + name: pkgJsonContents.name || 'N/A', + }; + } catch (err) { + console.log(`No package.json file was detected for path ${this.pathToPkgJson}.`); + return { + version: 'Version unknown', + name: 'Name unknown', + }; + } + } + + /** + * @param {Options|{}} newOptions + */ + setOptions(newOptions) { + // @ts-ignore + this.options = mergeDeep(this.options, newOptions); + + if (this.options.inputDir === 'FALLBACK') { + this.options.inputDir = path.join(this.options.cwd); + } + } + + /** + * @param {string} [configFile] + */ + async applyConfigFile(configFile) { + const _configFile = configFile || this.options.configFile; + if (_configFile) { + const configFilePath = path.resolve(_configFile); + const fileOptions = (await import(configFilePath)).default; + this.setOptions(fileOptions); + } else { + // make sure all default settings are properly initialized + this.setOptions({}); + } + } + + async prepare() { + let pluginsMeta = []; + for (const commandsUrl of this.config.commandsUrls) { + const commandFileDir = fs.readdirSync(commandsUrl); + for (const commandFile of commandFileDir) { + const commandImport = await import(`${commandsUrl.pathname}/${commandFile}`); + const command = commandImport[Object.keys(commandImport)[0]]; + pluginsMeta.push({ plugin: command, options: {} }); + } + } + if (Array.isArray(this.options.setupCliPlugins)) { + for (const setupFn of this.options.setupCliPlugins) { + // @ts-ignore + pluginsMeta = setupFn(pluginsMeta); + } + } + + for (const pluginObj of pluginsMeta) { + const pluginInst = pluginObj.options + ? // @ts-ignore + new pluginObj.plugin(pluginObj.options) + : // @ts-ignore + new pluginObj.plugin(); + this.config.plugins.push(pluginInst); + } + } + + async start() { + await this.applyConfigFile(); + await this.prepare(); + + if (!this.config.plugins) { + return; + } + + for (const plugin of this.config.plugins) { + if (plugin.setupCommand) { + await plugin.setupCommand(this.program, this); + } + } + try { + await this.program.parseAsync(this.config.argv); + } catch (error) { + // @ts-ignore + if (error.action) { + // @ts-ignore + await error.action(); + } + throw error; + } + } + + async stop({ hard = true } = {}) { + if (!this.config.plugins) { + return; + } + for (const plugin of this.config.plugins) { + if (plugin.stop) { + await plugin.stop({ hard }); + } + } + } +} diff --git a/packages-node/migrate-cli/src/cli-helpers/AsyncEventEmitter.js b/packages-node/migrate-cli/src/cli-helpers/AsyncEventEmitter.js new file mode 100644 index 0000000000..0417325777 --- /dev/null +++ b/packages-node/migrate-cli/src/cli-helpers/AsyncEventEmitter.js @@ -0,0 +1,21 @@ +import { EventEmitter } from 'events'; + +/** + * This class emits events asynchronously. + * It can be used for time measurements during a build. + */ +export class AsyncEventEmitter extends EventEmitter { + /** + * @param {string} type - The event name to emit. + * @param {*[]} args - Additional arguments that get passed to listeners. + * @returns {Promise<*[]>} - Promise resolves once all listeners were invoked + */ + async dispatchEventDone(type, ...args) { + const listeners = this.listeners(type); + if (listeners.length === 0) { + return []; + } + + return Promise.all(listeners.map(listener => listener.apply(this, args))); + } +} diff --git a/packages-node/migrate-cli/src/cli-helpers/mergeDeep.js b/packages-node/migrate-cli/src/cli-helpers/mergeDeep.js new file mode 100644 index 0000000000..a9d414ee7a --- /dev/null +++ b/packages-node/migrate-cli/src/cli-helpers/mergeDeep.js @@ -0,0 +1,30 @@ +/* eslint-disable no-param-reassign */ +// @ts-nocheck + +/** + * Performs a deep merge of objects and returns new object. Does not modify + * objects (immutable) and merges arrays via concatenation. + * + * @param {...object} objects - Objects to merge + * @returns {object} New object with merged key/values + */ +export function mergeDeep(..._objects) { + const isObject = obj => obj && typeof obj === 'object'; + const objects = _objects.filter(object => isObject(object)); + return objects.reduce((prev, obj) => { + Object.keys(obj).forEach(key => { + const pVal = prev[key]; + const oVal = obj[key]; + + if (Array.isArray(pVal) && Array.isArray(oVal)) { + prev[key] = pVal.concat(...oVal); + } else if (isObject(pVal) && isObject(oVal)) { + prev[key] = mergeDeep(pVal, oVal); + } else { + prev[key] = oVal; + } + }); + + return prev; + }, {}); +} diff --git a/packages-node/migrate-cli/src/cli.js b/packages-node/migrate-cli/src/cli.js new file mode 100755 index 0000000000..745b36d4e9 --- /dev/null +++ b/packages-node/migrate-cli/src/cli.js @@ -0,0 +1,25 @@ +#!/usr/bin/env node + +import { existsSync } from 'fs'; +import path from 'path'; +import { MigrateCli } from './MigrateCli.js'; + +const cli = new MigrateCli(); + +const cwd = process.cwd(); +const configFiles = [ + path.join('config', 'migrate-cli.config.js'), + path.join('config', 'migrate-cli.config.mjs'), + 'migrate-cli.config.js', + 'migrate-cli.config.mjs', +]; + +for (const configFile of configFiles) { + const configFilePath = path.join(cwd, configFile); + if (existsSync(configFilePath)) { + cli.options.configFile = configFilePath; + break; + } +} + +await cli.start(); diff --git a/packages-node/migrate-cli/src/commands/UpgradeCommandBase.js b/packages-node/migrate-cli/src/commands/UpgradeCommandBase.js new file mode 100644 index 0000000000..c9fcae7366 --- /dev/null +++ b/packages-node/migrate-cli/src/commands/UpgradeCommandBase.js @@ -0,0 +1,340 @@ +/* eslint-disable no-empty, class-methods-use-this, no-use-before-define, no-await-in-loop, no-console */ +import fs from 'fs'; +import path, { isAbsolute } from 'path'; +import { globby } from 'globby'; +import * as readline from 'readline'; + +import { Option, Command } from 'commander'; +import { executeJsCodeShiftTransforms } from '../migrate-helpers/executeJsCodeShiftTransforms.js'; + +export const consoleColorHelpers = { + reset: '\x1b[0m', + error: '\x1b[41m', +}; + +/** + * @param {URL|string} upgradesDir + * @returns {URL} + */ +function getUpgradesDirUrl(upgradesDir) { + if (upgradesDir instanceof URL) { + return upgradesDir; + } + if (!(typeof upgradesDir === 'string')) { + throw new Error('upgradesDir should be a URL or a string'); + } + try { + return new URL(upgradesDir); + } catch (e) {} + try { + const absolutePath = isAbsolute(upgradesDir) ? upgradesDir : path.resolve(upgradesDir); + return new URL(`file://${absolutePath}`); + } catch (e) { + throw new Error('Provided upgradesDir cannot be converted to a URL.'); + } +} + +/** + * @param {string} msg + * @param {{shouldPrompt: boolean}} options + * @returns {Promise|void} + */ +function logErrorAndPromptForContinue(msg, { shouldPrompt }) { + console.error(`${consoleColorHelpers.error} ${msg} ${consoleColorHelpers.reset} \n`); + + if (!shouldPrompt) return undefined; + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + return new Promise(resolve => { + rl.question('Do you want to continue (y/n)?', answer => { + const shouldContinue = answer.toLowerCase() === 'y'; + rl.close(); + + if (!shouldContinue) { + process.exit(0); + } + resolve(undefined); + }); + rl.write('y'); + }); +} + +/** + * @param {string} task + * @param {URL} upgradesDirUrl + * @returns {URL} + */ +function getUpgradeTaskUrl(task, upgradesDirUrl) { + return new URL(`./${task}/index.js`, upgradesDirUrl); +} + +/** + * @param {string} inputDir + */ +async function getRepoInfo(inputDir) { + const packageJsonPath = path.join(inputDir, 'package.json'); + let pkgJson; + try { + pkgJson = JSON.parse((await fs.promises.readFile(packageJsonPath)).toString()); + } catch { + return { isInvalidPackage: true, workspaces: [] }; + } + const isMonoRepo = Boolean(pkgJson.workspaces); + const workspaces = []; + for (const w of pkgJson.workspaces || []) { + // eslint-disable-next-line no-await-in-loop + const packageDirs = await globby(w, { cwd: inputDir, onlyDirectories: true }); + workspaces.push(...packageDirs.map(p => path.join(inputDir, p))); + } + return { isMonoRepo, workspaces }; +} + +/** + * @param {{upgradeTaskUrl:URL|string; options:{inputDir:string;subclasserMode?:boolean;}; task:string; isRunningMultipleTasks?: boolean}} opts + */ +async function runUpgradeTask({ upgradeTaskUrl, options, task, isRunningMultipleTasks = false }) { + const importStr = typeof upgradeTaskUrl === 'string' ? upgradeTaskUrl : upgradeTaskUrl.toString(); + const script = await import(importStr); + + const { workspaces, isMonoRepo } = await _mockable.getRepoInfo(options.inputDir); + + const workspacePackages = [ + ...workspaces.map(dir => ({ dir, type: 'monorepo-workspace' })), + { + dir: options.inputDir, + type: isMonoRepo ? 'monorepo-root' : 'single-package', + }, + ]; + + for (const workspacePackage of workspacePackages) { + console.log( + `\n\n=== starting task ${task} for .${workspacePackage.dir.replace( + options.inputDir, + '', + )} ===`, + ); + const { isInvalidPackage } = await _mockable.getRepoInfo(workspacePackage.dir); + if (isInvalidPackage) { + console.error(`package.json not found for ${workspacePackage.dir}. Skipping codemods...`); + // eslint-disable-next-line no-continue + continue; + } + + const workspaceMeta = { + monoRoot: workspaces.length ? options.inputDir : null, + type: workspacePackage.type, + workspacePackages, + }; + try { + await script._mockable.upgrade( + { + skipPackageJson: false, + transformFunction: executeJsCodeShiftTransforms, + ...options, + inputDir: workspacePackage.dir, + }, + workspaceMeta, + ); + } catch (e) { + // not all mono packages may apply: give + const fullMsg = `${e}`; + const relevantMsg = fullMsg.replace(/^Error:/, 'Warning:'); + await logErrorAndPromptForContinue(relevantMsg, { + shouldPrompt: isRunningMultipleTasks, + }); + } + } +} + +export class UpgradeCommandBase { + /** + * @param {import('commander').Command} program + * @param {import('../MigrateCli.js').MigrateCli} cli + */ + async setupCommand(program, cli) { + this.cli = cli; + this.program = program; + this.active = true; + this.addHelpText(); + const command = new Command('upgrade'); + this.setCommandOptions(command); + command.action(async options => { + // if config file is provided, first apply this before applying other options + const { configFile, ..._options } = options; + if (configFile) { + cli.applyConfigFile(configFile); + } + cli.setOptions(_options); + // eslint-disable-next-line no-param-reassign + cli.activePlugin = this; + await this.upgrade(); + }); + this.program.addCommand(command); + } + + /** + * + * @param {import('commander').Command} command + */ + setCommandOptions(command) { + command.addOption( + new Option( + '-i, --input-dir ', + 'path to where to search for source files (default to current directory)', + ), + ); + command.addOption( + new Option('-t, --task ', 'what upgrade task do you want to run [lib-foo-2-to-3]'), + ); + command.addOption( + new Option('-u, --upgrades-dir ', 'directory for upgrades tasks'), + ); + command.addOption(new Option('--include-ts', 'to apply the "upgrade" to ts files')); + command.addOption( + new Option( + '--skip-package-json', + 'skips package.json checks and updates. Can be handy for mono repos including docs folders etc.', + ), + ); + command.addOption(new Option('-c, --config-file ', 'path of a config file')); + } + + addHelpText() { + this.program?.addHelpText( + 'after', + [ + '', + 'Example call:', + ' $ npx migrate-cli upgrade -t lib-foo-1-to-2 -u /path/to/upgrades/dir', + '', + ].join('\n'), + ); + } + + async setTransformOptions() { + const { upgradeTaskUrl, upgradesDir } = /** @type {import('../MigrateCli.js').MigrateCli} */ ( + this.cli + ).options; + // At least one task or a base directory for a number of tasks is required for the codemod to run + if (upgradeTaskUrl || upgradesDir) { + return; + } + throw new Error( + 'The Upgrade Command is not properly configured. Please override the setTransformOptions method, or provide an upgrade location.', + ); + } + + async setUpgradesConfig() { + const { upgradesConfigHref, _upgradesDirUrl } = + /** @type {import('../MigrateCli.js').MigrateCli} */ (this.cli).options; + if (!upgradesConfigHref && !_upgradesDirUrl) { + return; + } + + // Fetch codemod specific config + const upgradesConfigUrl = + upgradesConfigHref || new URL('upgrades.config.js', _upgradesDirUrl).pathname; + const upgradesConfig = fs.existsSync(upgradesConfigUrl) + ? (await import(upgradesConfigUrl)).default + : {}; + /** @type {import('../MigrateCli.js').MigrateCli} */ (this.cli).setOptions(upgradesConfig); + } + + /** + * @param {string} task + */ + async getTaskDetails(task) { + const { _upgradesDirUrl } = /** @type {import('../MigrateCli.js').MigrateCli} */ (this.cli) + .options; + if (_upgradesDirUrl && this.cli) { + /** @type {import('../MigrateCli.js').MigrateCli} */ this.cli.options.upgradeTaskUrl = + getUpgradeTaskUrl(task, _upgradesDirUrl); + } + } + + async upgrade() { + if (!this.cli) { + return; + } + + const { task, upgradeTaskUrl } = this.cli.options; + + if (!task && !upgradeTaskUrl) { + throw new Error(`Please provide a task via -t`); + } + const taskString = /** @type {string} */ (task); + await this.setTransformOptions(); + const { upgradesDir } = this.cli.options; + const upgradesDirUrl = upgradesDir ? _mockable.getUpgradesDirUrl(upgradesDir) : undefined; + /** @type {import('../MigrateCli.js').MigrateCli} */ (this.cli).options._upgradesDirUrl = + upgradesDirUrl; + + await this.setUpgradesConfig(); + + await this.getTaskDetails(taskString); + + if (fs.existsSync(this.cli.options.upgradeTaskUrl)) { + await _mockable.runUpgradeTask({ + upgradeTaskUrl: this.cli.options.upgradeTaskUrl, + options: this.cli.options, + task: taskString, + }); + } else if (this.cli.options.allowedCompositeTasks?.get(taskString) && upgradesDirUrl) { + const upgradeTasks = this.cli.options.allowedCompositeTasks.get(taskString) || []; + const availableTasks = fs.readdirSync(new URL(upgradesDirUrl)); + let continueCombined = true; + upgradeTasks.forEach(partialTask => { + if (!availableTasks.includes(partialTask)) { + continueCombined = false; + } + }); + + if (continueCombined && upgradeTasks.length > 0 && availableTasks.length > 0) { + console.log( + `You are running the following codemods in composite mode: [${upgradeTasks.join( + ', ', + )}]. If your goal is to do checks inbetween codemods, please run them individually.`, + ); + + for (const _upgradeTask of upgradeTasks) { + // TODO: consider `--interactive` option, allowing to diff and run test intermediately + // eslint-disable-next-line no-await-in-loop + await _mockable.runUpgradeTask({ + upgradeTaskUrl: getUpgradeTaskUrl(_upgradeTask, upgradesDirUrl), + options: this.cli.options, + task: _upgradeTask, + isRunningMultipleTasks: true, + }); + } + + console.log( + `\n\nFinished running the following codemods in composite mode: [${upgradeTasks.join( + ', ', + )}].`, + ); + } + } else { + console.log(`No upgrade task with the name "${task}" found.`); + console.log(''); + console.log('Available upgrade tasks are:'); + for (const taskName of [ + ...this.cli.options.upgradeTaskNames, + ...(this.cli.options.allowedCompositeTasks || []), + ]) { + console.log(`- ${taskName}`); + } + console.log(''); + console.log('Or check the upgradeTaskUrl in your config.'); + } + } +} + +export const _mockable = { + getRepoInfo, + runUpgradeTask, + getUpgradesDirUrl, +}; diff --git a/packages-node/migrate-cli/src/migrate-helpers/executeJsCodeShiftTransforms.js b/packages-node/migrate-cli/src/migrate-helpers/executeJsCodeShiftTransforms.js new file mode 100644 index 0000000000..8d27a52714 --- /dev/null +++ b/packages-node/migrate-cli/src/migrate-helpers/executeJsCodeShiftTransforms.js @@ -0,0 +1,220 @@ +/* eslint-disable no-console */ +// @ts-ignore +import { run as jscodeshift } from 'jscodeshift/src/Runner.js'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; +import { globby } from 'globby'; +import { getJsBlocksFromMdFiles } from './getJsBlocksFromMdFiles.js'; + +/** + * @typedef {import('../../types/index.js').WorkspaceMeta}WorkspaceMeta + */ + +function captureLogs({ + shouldCaptureConsole = true, + shouldCaptureStdout = false, + shouldDebug = false, +}) { + /** + * @type {[any?, ...any[]][]} + */ + const capturedLogs = []; + const originalLogs = {}; + /** + * @type {(() => void)[]} + */ + const restoreLogFns = []; + + if (shouldCaptureConsole) { + for (const logType of ['error', 'warn', 'info', 'log']) { + originalLogs[logType] = console[logType]; + // eslint-disable-next-line no-param-reassign + console[logType] = (/** @type {[any?, ...any[]]} */ ...args) => { + capturedLogs.push(args); + if (shouldDebug) { + originalLogs[logType](...args); + } + }; + + restoreLogFns.push(() => { + // eslint-disable-next-line no-param-reassign + console[logType] = originalLogs[logType]; + }); + } + } + + const stdoutOriginalWrite = process.stdout.write; + + if (shouldCaptureStdout) { + // https://github.com/facebook/jscodeshift/blob/51da1a5c4ba3707adb84416663634d4fc3141cbb/src/Runner.js#L42 + // @ts-ignore + process.stdout.write = (...args) => { + // @ts-ignore + capturedLogs.push([args[0].toString()]); + // if (shouldDebug) { + // stdoutOriginalWrite(...args); + // } + }; + } + + const restore = () => { + for (const restoreLogFn of restoreLogFns) { + restoreLogFn(); + } + process.stdout.write = stdoutOriginalWrite; + }; + + return { capturedLogs, restore }; +} + +/** + * @param {string} sourceFile + */ +function hasReservedMdName(sourceFile) { + for (const fileNameInclude of ['CHANGELOG', 'README', 'CONTRIBUTING', 'MIGRATION']) { + const fileName = path.basename(sourceFile, '.md'); + if (fileName.includes(fileNameInclude)) { + return true; + } + } + return false; +} + +/** + * @param {string | URL} inputDir + * @param {string | URL} transformsFolder + * @param {*} [jscOptions] + * @param {{customPaths?:string[]; shouldDebug?: boolean; workspaceMeta?:WorkspaceMeta}} extraOpts + */ +export async function executeJsCodeShiftTransforms( + inputDir, + transformsFolder, + jscOptions = {}, + { customPaths, shouldDebug = false, workspaceMeta } = {}, +) { + const excludePaths = + workspaceMeta?.type === 'monorepo-root' + ? workspaceMeta.workspacePackages.filter(w => w.type === 'monorepo-workspace').map(w => w.dir) + : []; + + const transformsPath = + transformsFolder instanceof URL ? fileURLToPath(transformsFolder) : transformsFolder; + const inputDirPath = inputDir instanceof URL ? fileURLToPath(inputDir) : inputDir; + const transformFiles = await fs.promises.readdir(transformsPath); + /** @type {string[]} */ + let sourceFiles; + const supportedFileTypes = ['mjs', 'js', 'cjs', 'md', 'mdx', 'ts']; + if (!Array.isArray(customPaths)) { + sourceFiles = ( + await globby([`**/*.{${supportedFileTypes.join(',')}}`], { + cwd: inputDirPath, + ignore: ['**/node_modules/**', '**/bower_components/**'], + }) + ).map(file => path.join(inputDirPath, file)); + } else { + sourceFiles = customPaths; + } + + const hiddenStorybookPath = `${inputDirPath}/.storybook`; + // We skip hidden folders, except for storybook folder + const hiddenStorybookConfigFiles = ( + await globby([`**/*.{${supportedFileTypes.join(',')}}`], { + cwd: hiddenStorybookPath, + }) + ).map(file => path.join(hiddenStorybookPath, file)); + + const jsSourceFiles = []; + const mdSourceFiles = []; + for (const sourceFile of [...sourceFiles, ...hiddenStorybookConfigFiles]) { + if (sourceFile.endsWith('.md') || sourceFile.endsWith('.mdx')) { + if (hasReservedMdName(sourceFile)) { + // eslint-disable-next-line no-continue + continue; + } + mdSourceFiles.push(sourceFile); + } else { + if (sourceFile.endsWith('.ts') && !jscOptions.includeTs) { + // eslint-disable-next-line no-continue + continue; + } + // all other extensions are considered js + jsSourceFiles.push(sourceFile); + } + } + const { updateJsBlocksMdFiles, tmpBlockFilePaths } = await getJsBlocksFromMdFiles({ + mdFilePaths: mdSourceFiles, + }); + + const jsCodeShiftPaths = [...jsSourceFiles, ...tmpBlockFilePaths].filter( + p => !excludePaths.find(ep => p.startsWith(ep)), + ); + + console.log(`🔎 Found ${jsCodeShiftPaths.length} files to transform`); + + let fullRes = { + timeElapsed: '0', + nochange: 0, + error: 0, + skip: 0, + ok: 0, + }; + + const cjsTransformFiles = transformFiles.filter((/** @type string */ t) => + t.endsWith('_-_cjs-export.cjs'), + ); + for (const transformFile of cjsTransformFiles) { + const fullTransformFile = path.join(transformsPath, transformFile); + + // eslint-disable-next-line no-unused-vars + const { capturedLogs, restore } = captureLogs({ + shouldCaptureConsole: false, + shouldCaptureStdout: true, + shouldDebug, + }); + + const mergedOptions = { + // dry: true, + silent: false, + verbose: 2, + ...jscOptions, + ...(jscOptions?.includeTs ? { parser: 'ts' } : {}), + ...(shouldDebug ? { runInBand: false } : {}), + }; + + const niceName = path.basename(transformFile).replace('_-_cjs-export.cjs', ''); + console.log(`🚀 Running jscodeshift mod "${niceName}"`); + + const res = await jscodeshift(fullTransformFile, jsCodeShiftPaths, mergedOptions); + + restore(); + + // capturedLogs.forEach((/** @type {string[]} */ args) => { + // const noChange = args[0].startsWith('\x1B[37m\x1B[43m NOC'); + // const workerInfo = args[0].startsWith('Sending'); + // // if (noChange || workerInfo) { + + // // } + // }); + + fullRes = { + timeElapsed: `${parseFloat(fullRes.timeElapsed) + parseFloat(res.timeElapsed)}`, + nochange: fullRes.nochange + res.nochange, + error: fullRes.error + res.error, + skip: fullRes.skip + res.skip, + ok: fullRes.ok + res.ok, + }; + } + + await updateJsBlocksMdFiles(); + + if (fullRes.error > 0) { + console.log(`🛑 ${fullRes.error} files failed to update.`); + } + if (fullRes.skip > 0) { + console.log(`⚠️ ${fullRes.skip} files got skipped.`); + } + if (fullRes.ok > 0) { + console.log(`✅ ${fullRes.ok} files got updated successfully.`); + } +} diff --git a/packages-node/migrate-cli/src/migrate-helpers/getJsBlocksFromMdFiles.js b/packages-node/migrate-cli/src/migrate-helpers/getJsBlocksFromMdFiles.js new file mode 100644 index 0000000000..410ad09e7d --- /dev/null +++ b/packages-node/migrate-cli/src/migrate-helpers/getJsBlocksFromMdFiles.js @@ -0,0 +1,126 @@ +/* eslint-disable no-await-in-loop */ +import fs from 'fs'; +import path from 'path'; + +/** + * @typedef {{jsBody:string; index:number; tmpBlockFilePath:string; mdFilePath:string}} BlockResult + */ + +const TMP_DIR = `${process.cwd()}/_tmp-md-blocks`; + +/** + * @param {string|object} inputValue + * @returns {number} + */ +export function getHash(inputValue) { + if (typeof inputValue === 'object') { + // eslint-disable-next-line no-param-reassign + inputValue = JSON.stringify(inputValue); + } + return inputValue.split('').reduce( + (prevHash, currVal) => + // eslint-disable-next-line no-bitwise + ((prevHash << 5) - prevHash + currVal.charCodeAt(0)) | 0, + 0, + ); +} + +/** + * Call this when all codemods have run on extracted tmpBlockFilePaths + * + * @example + * ```js + * const { updateJsBlocksMdFiles } = await getJsBlocksFromMdFile({ mdFilePaths: ['/my/stories.md','/my/other-stories.md',] }); + * for (const mdFilePath of mdFilePaths) { + * await runCodemodsOnMdFile(mdFilePath); + * } + * await updateJsBlocksMdFiles(); + * ``` + * @param {BlockResult[]} blockResultsAllMdFiles + * @param {string} tmpDir + */ +async function updateJsBlocksMdFiles(blockResultsAllMdFiles, tmpDir) { + /** @type {{mdFilePath: string; blocks: BlockResult[]}[]} */ + const blockResultsOrderedByMdFile = []; + for (const blockResult of blockResultsAllMdFiles) { + const found = blockResultsOrderedByMdFile.find(e => e.mdFilePath === blockResult.mdFilePath); + if (found) { + found.blocks.push(blockResult); + } else { + blockResultsOrderedByMdFile.push({ + mdFilePath: blockResult.mdFilePath, + blocks: [blockResult], + }); + } + } + + for (const file of blockResultsOrderedByMdFile) { + if (!file.blocks?.length) { + // eslint-disable-next-line no-continue + continue; + } + let contentMdFile = await fs.promises.readFile(file.mdFilePath, 'utf-8'); + let shouldWrite = false; + for (const block of file.blocks) { + const newContent = await fs.promises.readFile(block.tmpBlockFilePath, 'utf-8'); + if (newContent !== block.jsBody) { + shouldWrite = true; + contentMdFile = contentMdFile.replace(block.jsBody, `${newContent}`); + } + } + if (shouldWrite) { + await fs.promises.writeFile(file.mdFilePath, contentMdFile); + } + } + // clean up temp folder + await fs.promises.rmdir(tmpDir, { recursive: true }); +} + +/** + * Extracts js code examples, writes them to fs, so they are ready to be processed by codemods. + * Returns a function to call when all codemods have run on extracted tmpBlockFilePaths + * + * @example + * ```js + * const { updateJsBlocksMdFiles } = await getJsBlocksFromMdFile({ mdFilePaths: ['/my/stories.md','/my/other-stories.md',] }); + * for (const mdFilePath of mdFilePaths) { + * await runCodemodsOnMdFile(mdFilePath); + * } + * await updateJsBlocksMdFiles(); + * ``` + * + * @param {{mdFilePaths:string[]; tmpDir?:string}} opts + * @returns {Promise<{updateJsBlocksMdFiles:function; tmpBlockFilePaths:string[]}>} + */ +export async function getJsBlocksFromMdFiles({ mdFilePaths, tmpDir = TMP_DIR }) { + /** @type {BlockResult[]} */ + const blockResultsAllMdFiles = []; + const tmpBlockFilePaths = []; + await fs.promises.mkdir(tmpDir, { recursive: true }); + + for (const mdFilePath of mdFilePaths) { + const mdContent = await fs.promises.readFile(mdFilePath, 'utf-8'); + const re = /(```js)(.*\n)((.|\n)*?)(```)/; + const allBlocks = mdContent.match(new RegExp(re, 'g')) || []; + const pendingWritePromises = []; + for (let i = 0; i < allBlocks.length; i += 1) { + const block = allBlocks[i]; + const [, , , jsBody] = block.match(re) || []; + const fileName = `h${getHash(mdFilePath.replace(process.cwd(), ''))}-${path.basename( + mdFilePath, + path.extname(mdFilePath), + )}-${i}.js`; + const tmpBlockFilePath = path.join(tmpDir, fileName); + tmpBlockFilePaths.push(tmpBlockFilePath); + const pendingWrite = fs.promises.writeFile(tmpBlockFilePath, jsBody); + pendingWritePromises.push(pendingWrite); + blockResultsAllMdFiles.push({ jsBody, index: i, tmpBlockFilePath, mdFilePath }); + } + await Promise.all(pendingWritePromises); + } + + return { + tmpBlockFilePaths, + updateJsBlocksMdFiles: () => updateJsBlocksMdFiles(blockResultsAllMdFiles, tmpDir), + }; +} diff --git a/packages-node/migrate-cli/src/migrate-helpers/verifyPackageJson.js b/packages-node/migrate-cli/src/migrate-helpers/verifyPackageJson.js new file mode 100644 index 0000000000..56fca3d786 --- /dev/null +++ b/packages-node/migrate-cli/src/migrate-helpers/verifyPackageJson.js @@ -0,0 +1,89 @@ +// @ts-expect-error +import { memoize } from 'providence-analytics/utils.js'; +import semver from 'semver'; +import path from 'path'; +import fs from 'fs'; + +/** + * @type {{[monoRoot:string]: string[]}} + */ + +/** + * @param {{monoRoot:string, depsToCheck:{name: string; minVersion?: string; }[];}} opts + * @returns {Promise} + */ +async function getMonoRootDepsUnMemoized({ monoRoot, depsToCheck }) { + const packageJsonPath = path.join(monoRoot, 'package.json'); + if (!fs.existsSync(packageJsonPath)) { + throw new Error(`package.json not found for ${monoRoot}. Please provide a correct monoRoot`); + } + + const packageJson = JSON.parse((await fs.promises.readFile(packageJsonPath)).toString()); + const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; + + const foundPackages = []; + for (const depToCheck of depsToCheck) { + // eslint-disable-next-line no-continue + if (!deps[depToCheck.name]) continue; + + if (depToCheck.minVersion) { + const coercedVersionFound = /** @type {* & string} */ (semver.coerce(deps[depToCheck.name])); + // eslint-disable-next-line no-continue + if (semver.lt(coercedVersionFound, depToCheck.minVersion)) continue; + } + foundPackages.push(depToCheck.name); + } + return foundPackages; +} + +const getMonoRootDeps = memoize(getMonoRootDepsUnMemoized, { serializeObjects: true }); + +/** + * For a given set of deps, checks whether they are used in package.json + * When a monoroot depends on package (usually via devDependencies), + * there will be no requirement for a workspace package to depend on it as well. + * @param {string} inputDir + * @param {{depsToCheck:{name: string; minVersion?: string; }[];monoRoot?:string;}} opts + * @returns {Promise} + */ +// @ts-ignore +export async function verifyPackageJson(inputDir, { depsToCheck, monoRoot } = {}) { + const isMonoRoot = inputDir === monoRoot; + let monoRootDeps = null; + if (!isMonoRoot) { + monoRootDeps = monoRoot ? await getMonoRootDeps({ monoRoot, depsToCheck }) : null; + } + + const packageJsonPath = path.join(inputDir, 'package.json'); + if (!fs.existsSync(packageJsonPath)) { + throw new Error( + `package.json not found for ${inputDir}. Please run this command in the root directory of your component/app.`, + ); + } + + const packageJson = JSON.parse((await fs.promises.readFile(packageJsonPath)).toString()); + const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; + + for (const depToCheck of depsToCheck) { + // eslint-disable-next-line no-continue + if (monoRootDeps?.includes(depToCheck.name)) continue; + + if (!deps[depToCheck.name]) { + throw new Error( + `package.json of ${inputDir} does not have ${depToCheck.name} as a dependency`, + ); + } + + if (depToCheck.minVersion) { + const coercedVersionFound = /** @type {* & string} */ (semver.coerce(deps[depToCheck.name])); + + if (semver.lt(coercedVersionFound, depToCheck.minVersion)) { + throw new Error( + `package.json of ${inputDir} is using version ${ + deps[depToCheck.name] + } of ${depToCheck.name}. You need to use at least version ${depToCheck.minVersion}`, + ); + } + } + } +} diff --git a/packages-node/migrate-cli/test-helpers/.gitignore b/packages-node/migrate-cli/test-helpers/.gitignore new file mode 100644 index 0000000000..1ba7dc3cb3 --- /dev/null +++ b/packages-node/migrate-cli/test-helpers/.gitignore @@ -0,0 +1 @@ +_temp-fixtures \ No newline at end of file diff --git a/packages-node/migrate-cli/test-helpers/mock-helpers.js b/packages-node/migrate-cli/test-helpers/mock-helpers.js new file mode 100644 index 0000000000..619c66258d --- /dev/null +++ b/packages-node/migrate-cli/test-helpers/mock-helpers.js @@ -0,0 +1,34 @@ +import path from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; + +/** + * TODO: remove this method if mock-fs works as expected + * @param {{[path:string]: string }} projectMock + * @param {{ projectName:string }} opts + */ +export async function createTempProjectFixture(projectMock, { projectName }) { + const projectPath = fileURLToPath(new URL(`./_temp-fixtures/${projectName}`, import.meta.url)); + + const pendingWrites = []; + for (const [localPath, content] of Object.entries(projectMock)) { + const finalPath = path.join(projectPath, localPath); + await fs.promises.mkdir(path.dirname(finalPath), { recursive: true }); + pendingWrites.push(fs.promises.writeFile(finalPath, content)); + } + + await Promise.all(pendingWrites); + return projectPath; +} + +/** + * @param {string} [projectName] + */ +export async function restoreTempProjectFixture(projectName) { + const pathToClean = fileURLToPath( + new URL(`./_temp-fixtures${projectName ? `/${projectName}` : ''}`, import.meta.url), + ) + .toString() + .replace(/^file:\/\//, ''); + await fs.promises.rm(pathToClean, { recursive: true }); +} diff --git a/packages-node/migrate-cli/test-helpers/pretty-format.js b/packages-node/migrate-cli/test-helpers/pretty-format.js new file mode 100644 index 0000000000..7ea386690a --- /dev/null +++ b/packages-node/migrate-cli/test-helpers/pretty-format.js @@ -0,0 +1,57 @@ +// @ts-ignore +import prettier from 'prettier'; + +/** + * + * @param {string} text + * @param {{format?:string|boolean;removeEndNewLine?:boolean;printWidth?:number;arrowParens?:'always'|'avoid'}} opts + * @returns + */ +export async function prettyFormat( + text, + { format = 'html', removeEndNewLine = false, printWidth = 100, arrowParens = 'always' } = {}, +) { + let useFormat = format; + switch (format) { + case 'html': + useFormat = 'html'; + break; + case 'js': + case 'babel': + useFormat = 'babel'; + break; + case 'md': + case 'markdown': + useFormat = 'markdown'; + break; + default: + useFormat = false; + } + + if (useFormat === false) { + return text; + } + + let formatted = await prettier.format(text, { + parser: useFormat, + printWidth, + arrowParens, + singleQuote: true, + }); + // remove all empty lines for html + if (useFormat === 'html') { + formatted = formatted + .split('\n') + .filter((/** @type {string|undefined} */ line) => line?.trim()) + .join('\n'); + } + + // remove end newline + if (removeEndNewLine) { + if (formatted.charAt(formatted.length - 1) === '\n') { + formatted = formatted.substring(0, formatted.length - 1); + } + } + + return formatted; +} diff --git a/packages-node/migrate-cli/test-helpers/test-helpers.js b/packages-node/migrate-cli/test-helpers/test-helpers.js new file mode 100644 index 0000000000..5a82eb425e --- /dev/null +++ b/packages-node/migrate-cli/test-helpers/test-helpers.js @@ -0,0 +1,303 @@ +import path, { basename } from 'path'; +import { existsSync, readFileSync } from 'fs'; +import { rm, writeFile, mkdir, rename } from 'fs/promises'; +import { fileURLToPath, pathToFileURL } from 'url'; +// @ts-ignore +import fsExtraPkg from 'fs-extra'; +// @ts-ignore +import * as chai from 'chai'; +// @ts-ignore +import { applyTransform } from 'jscodeshift/dist/testUtils.js'; +// eslint-disable-next-line import/no-relative-packages +import { prettyFormat } from './pretty-format.js'; +import { MigrateCli } from '../src/MigrateCli.js'; + +const { copy, move, remove } = fsExtraPkg; + +/** + * @param {string} cwd + * @param {{cliArgv:string[];cliOptions?:{inputDir?:string;outputDir?:string;outputDevDir?:string};testOptions:{captureLogs?:boolean}}} opts + * @param {string} dir + */ +export async function setupTestCli(cwd, { cliArgv = [], cliOptions = {}, testOptions = {} }, dir) { + const resolvedCwd = cwd.startsWith('/') ? cwd : path.join(dir, cwd.split('/').join(path.sep)); + const useOptions = { ...cliOptions, cwd: resolvedCwd }; + if (useOptions.inputDir) { + useOptions.inputDir = path.join(dir, useOptions.inputDir.split('/').join(path.sep)); + } + useOptions.outputDir = path.join(resolvedCwd, '__output'); + useOptions.outputDevDir = path.join(resolvedCwd, '__output-dev'); + + /** @type {string[]} */ + const capturedLogs = []; + const origConsole = console; + if (testOptions.captureLogs) { + console.log = msg => { + capturedLogs.push(msg); + }; + console.error = msg => { + capturedLogs.push(msg); + }; + } + + const cli = new MigrateCli({ + argv: [ + process.argv[0], + fileURLToPath(new URL(pathToFileURL('../src/cli.js'), import.meta.url)), + ...cliArgv, + ], + }); + const configFiles = [ + path.join('config', 'ing-web-cli.config.js'), + path.join('config', 'ing-web-cli.config.mjs'), + 'ing-web-cli.config.js', + 'ing-web-cli.config.mjs', + ]; + for (const configFile of configFiles) { + const configFilePath = path.join(resolvedCwd, configFile); + if (existsSync(configFilePath)) { + cli.options.configFile = configFilePath; + break; + } + } + cli.setOptions(useOptions); + + /** + * @param {string} toInspect + * @param {{format?:string}} opts + */ + async function readOutput(toInspect, { format = 'auto' } = {}) { + // @ts-expect-error + const filePath = path.join(cli.options.outputDir, toInspect); + if (!existsSync(filePath)) { + throw new Error(`Rendering to ${toInspect} did not happen\nFull path: ${filePath}`); + } + let text = readFileSync(filePath).toString(); + + const useFormat = format === 'auto' ? toInspect.split('.').pop() : format; + if (useFormat) { + text = await prettyFormat(text, { format: useFormat, removeEndNewLine: true }); + } + return text; + } + + /** + * @param {string} toInspect + * @param {{format?:string}} opts + */ + async function readDevOutput(toInspect, { format = 'auto' } = {}) { + // @ts-expect-error + const filePath = path.join(cli.options.outputDevDir, toInspect); + if (!existsSync(filePath)) { + throw new Error(`Rendering to ${toInspect} did not happen\nFull path: ${filePath}`); + } + let text = readFileSync(filePath).toString(); + + const useFormat = format === 'auto' ? toInspect.split('.').pop() : format; + if (useFormat) { + text = await prettyFormat(text, { format: useFormat, removeEndNewLine: true }); + } + return text; + } + + /** + * @param {string} toInspect + * @param {{format?:string|boolean}} opts + */ + async function readSource(toInspect, { format = 'auto' } = {}) { + const filePath = path.join(cli.options.inputDir, toInspect); + let text = readFileSync(filePath).toString(); + const useFormat = format === 'auto' ? toInspect.split('.').pop() : format; + if (useFormat) { + text = await prettyFormat(text, { format: useFormat, removeEndNewLine: true }); + } + return text.replace(/\r/g, ''); // Convert Windows EOL to POSIX EOL to be consistent with test assertions. + } + + /** + * @param {string} toInspect + * @param {string} text + * @param {{format?:string}} opts + */ + async function writeSource(toInspect, text, { format = 'auto' } = {}) { + let formattedText = text; + const filePath = path.join(cli.options.inputDir, toInspect); + const dirName = path.dirname(filePath); + if (!existsSync(dirName)) { + await mkdir(dirName, { recursive: true }); + } + + const useFormat = format === 'auto' ? toInspect.split('.').pop() : format; + if (useFormat) { + formattedText = await prettyFormat(text, { format: useFormat }); + } + await writeFile(filePath, formattedText); + } + + /** + * @param {string} toInspect + */ + async function deleteSource(toInspect) { + const filePath = path.join(cli.options.inputDir, toInspect); + await rm(filePath, { force: true, recursive: true }); + } + + /** + * @param {string} fromRelativePath + * @param {string} toRelativePath + */ + async function renameSource(fromRelativePath, toRelativePath) { + const fromPath = path.join(cli.options.inputDir, fromRelativePath); + const toPath = path.join(cli.options.inputDir, toRelativePath); + await rename(fromPath, toPath); + } + + /** + * @param {string} toInspect + */ + function sourceExists(toInspect) { + const filePath = path.join(cli.options.inputDir, toInspect); + return existsSync(filePath); + } + + async function cleanup() { + await cli.stop({ hard: false }); + + if (testOptions.captureLogs) { + console.log = origConsole.log; + console.error = origConsole.error; + } + } + + async function start() { + await cli.start(); + await cleanup(); + } + + async function restoreSource({ keepBackup = false } = {}) { + const backupDir = path.join( + cli.options.inputDir, + '..', + `${basename(cli.options.inputDir)}-__backup`, + ); + if (existsSync(backupDir)) { + await remove(cli.options.inputDir); + if (keepBackup === false) { + await move(backupDir, cli.options.inputDir); + } else { + await copy(backupDir, cli.options.inputDir); + } + } + } + + async function backupOrRestoreSource() { + const backupDir = path.join( + cli.options.inputDir, + '..', + `${basename(cli.options.inputDir)}-__backup`, + ); + if (existsSync(backupDir)) { + await restoreSource({ keepBackup: true }); + } else { + await copy(cli.options.inputDir, backupDir); + } + } + + return { + readOutput, + readDevOutput, + readSource, + writeSource, + deleteSource, + cleanup, + start, + cli, + sourceExists, + renameSource, + backupOrRestoreSource, + restoreSource, + capturedLogs, + }; +} + +/** + * @param {string} importMetaUrl + */ +export function prepareTestCli(importMetaUrl) { + const dir = path.dirname(fileURLToPath(importMetaUrl)); + return ( + /** @type {string} */ cwd, + /** @type {{cliArgv:string[];cliOptions?:{inputDir?:string;outputDir?:string;outputDevDir?:string; _upgradeTaskUrl?:string;};testOptions:{captureLogs?:boolean}}} */ options, + ) => setupTestCli(cwd, options, dir); +} + +/** + * @param {function} method + * @param {{errorMatch?: RegExp; errorMessage?: string}} opts + */ +export async function expectThrowsAsync(method, { errorMatch, errorMessage } = {}) { + let error = null; + try { + await method(); + } catch (err) { + error = err; + } + chai.expect(error).to.be.an('Error', 'No error was thrown'); + if (errorMatch) { + // @ts-ignore + chai.expect(error.message).to.match(errorMatch); + } + if (errorMessage) { + // @ts-ignore + chai.expect(error.message).to.equal(errorMessage); + } +} + +/** + * @param {*} module + * @param {object} options + * @param {{source:string}} input + * @param {string} expectedOutput + * @param {object} testOptions + * @returns + */ +export async function runInlineTest(module, options, input, expectedOutput, testOptions) { + const output = applyTransform(module, options, input, testOptions); + chai + .expect(await prettyFormat(output, { format: 'js' })) + .to.equal(await prettyFormat(expectedOutput, { format: 'js' })); + return output; +} + +/** + * @param {{transform:(file:{source:string; path:string}, api:{jscodeshift:import('jscodeshift')}, options?:any) => string, transformOptions?:object, testOptions?: object}} config + */ +export function createCompare({ transform, transformOptions = {}, testOptions = {} }) { + /** + * @param {{options?:object, from:string, to:string}} config + */ + return function compare({ options = transformOptions, from, to }) { + runInlineTest(transform, options, { source: from }, to, testOptions); + }; +} + +/** + * @param {function} fn + */ +export function createCompareFromFn(fn) { + return createCompare({ + transform: { + parser: 'babel', + /** + * @param {{ source: import('jscodeshift').File }} file + * @param {{ jscodeshift: import('jscodeshift') }} api + */ + default: (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + fn({ root, j }); + return root.toSource(); + }, + }, + }); +} diff --git a/packages-node/migrate-cli/test-helpers/types.ts b/packages-node/migrate-cli/test-helpers/types.ts new file mode 100644 index 0000000000..562b399908 --- /dev/null +++ b/packages-node/migrate-cli/test-helpers/types.ts @@ -0,0 +1,26 @@ +export type MockBridgeOpts = { + extraMock?: object; + extraPkgJsonDeps?: object; + extraPkgJsonDevDeps?: object; + projectName?: string; + iw1Features?: 0 | 1 | 2; + iw2Features?: 0 | 1 | 2; + iw3Features?: 0 | 1 | 2; + iw3?: boolean; + iw2?: boolean; + iw1?: boolean; + litElement2?: boolean; + litElement3?: boolean; + litHtml1?: boolean; + litHtml2?: boolean; + scopedElements1?: boolean; + scopedElements2?: boolean; + legacyAjax?: boolean; + bridge?: boolean; + hoistCfg?: { + iw?: 1 | 2 | 3; + litElement?: 2 | 3; + litHtml?: 1 | 2; + scopedElements?: 1 | 2; + }; +}; diff --git a/packages-node/migrate-cli/test/CLI/MigrateCli.test.js b/packages-node/migrate-cli/test/CLI/MigrateCli.test.js new file mode 100644 index 0000000000..1b7de549c0 --- /dev/null +++ b/packages-node/migrate-cli/test/CLI/MigrateCli.test.js @@ -0,0 +1,63 @@ +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { MigrateCli } from '../../src/MigrateCli.js'; + +chai.use(chaiAsPromised); +const { expect } = chai; + +describe('MigrateCli works as a base CLI', () => { + describe('initialisation and preparation of the CLI works as expected', () => { + /** @type {import('../../src/MigrateCli.js').MigrateCli} */ let cli; + + beforeEach(() => { + cli = new MigrateCli(); + }); + + it('initialises CLI with base command with minimal config', () => { + expect(cli.program).to.exist; + expect(cli.options.inputDir).to.equal('FALLBACK'); + expect(cli.program.helpInformation()).to.contain('--version'); + const { version, name } = cli.getNameAndVersion(); + expect(cli.program.version()).to.equal(version); + expect(cli.program.name()).to.equal(name); + }); + + it('prepares a base plugin without specific config', async () => { + await cli.prepare(); + expect(cli.config.plugins.length).to.equal(1); + }); + + it('accepts additional commands if so configured', async () => { + cli = new MigrateCli({ + includeBaseCommands: true, + commandsUrls: [new URL('../mocks/commands', import.meta.url)], + }); + await cli.prepare(); + expect(cli.config.plugins.length).to.equal(2); + }); + + it('starts the CLI as expected', async () => { + cli.config.commandsUrls = [new URL('../mocks/commands', import.meta.url)]; + cli.config.argv = ['/bin/node', '/migrate-cli/src/cli.js', 'mock']; + await cli.start(); + expect(cli.activePlugin.program.args).to.include('mock'); + expect(cli.activePlugin.active).to.be.true; + }); + + it('applies a config file', async () => { + const options = { + inputDir: 'inputDir', + configFile: new URL('../mocks/config-file-1.js', import.meta.url).pathname, + upgradesDir: 'upgradesDir', + task: 'task', + }; + cli.setOptions(options); + expect(cli.options.inputDir).to.equal(options.inputDir); + expect(cli.options.upgradesDir).to.equal(options.upgradesDir); + await cli.applyConfigFile(); + expect(cli.options.inputDir).to.equal('otherInputDir'); + expect(cli.options.upgradesDir).to.equal('otherUpgradesDir'); + expect(cli.options.task).to.equal(options.task); + }); + }); +}); diff --git a/packages-node/migrate-cli/test/CLI/cli.test.js b/packages-node/migrate-cli/test/CLI/cli.test.js new file mode 100644 index 0000000000..1e28023bdc --- /dev/null +++ b/packages-node/migrate-cli/test/CLI/cli.test.js @@ -0,0 +1,318 @@ +import { expect } from 'chai'; +import { setupTestCli } from '../../test-helpers/test-helpers.js'; +import { + createTempProjectFixture, + restoreTempProjectFixture, +} from '../../test-helpers/mock-helpers.js'; + +// TODO: for some reason tests are failing until path is changed or ran in isolation +describe('cli upgrade function (using verifyPackageJson with workspaceMeta)', () => { + after(() => { + restoreTempProjectFixture(); + }); + + it('works on monorepos', async () => { + const monoRepo = { + 'upgrade/index.js': ` + import { executeJsCodeShiftTransforms } from '../../../../src/migrate-helpers/executeJsCodeShiftTransforms.js'; + import { verifyPackageJson } from '../../../../src/migrate-helpers/verifyPackageJson.js'; + + export async function upgrade({ inputDir, jscsOpts }, workspaceMeta) { + await verifyPackageJson(inputDir, { + depsToCheck: [{ name: 'dep-foo', minVersion: '1.0.0' }], + monoRoot: workspaceMeta.monoRoot, + }); + + await executeJsCodeShiftTransforms( + inputDir, + new URL('./jscodeshift/', import.meta.url), + {...jscsOpts, includeTs: true}, + { workspaceMeta }, + ); + } + + export const _mockable = { upgrade }; + `, + 'upgrade/jscodeshift/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + 'package.json': JSON.stringify({ + version: '1.0.0', + type: 'module', + name: 'mono-root', + workspaces: ['packages/*'], + }), + // is considered, bc dep + 'packages/pkg-a/package.json': JSON.stringify({ + version: '1.0.0', + type: 'module', + name: 'pkg-a', + dependencies: { 'dep-foo': '2.0.0' }, + }), + 'packages/pkg-a/file.js': ['export const updated = false'].join('\n'), + 'packages/pkg-a/tsfile.ts': ['export const updated = false'].join('\n'), + // is considered, bc devDep + 'packages/pkg-b/package.json': JSON.stringify({ + version: '1.0.0', + type: 'module', + name: 'pkg-b', + devDependencies: { 'dep-foo': '2.0.0' }, + }), + 'packages/pkg-b/file.js': ['export const updated = false'].join('\n'), + // is not considered, bc no dep + 'packages/pkg-c/package.json': JSON.stringify({ + version: '1.0.0', + type: 'module', + name: 'pkg-c', + }), + 'packages/pkg-c/file.js': ['export const updated = false'].join('\n'), + // is not considered, bc no workspace + 'not-workspace/pkg-dpackage.json': JSON.stringify({ + type: 'module', + name: 'pkg-d', + }), + 'not-workspace/pkg-d/file.js': ['export const updated = false'].join('\n'), + }; + + const projectPath = await createTempProjectFixture(monoRepo, { + projectName: 'monoRepo', + }); + + const { start, backupOrRestoreSource, restoreSource, readSource } = await setupTestCli( + projectPath, + { + cliArgv: ['upgrade', '-t', '_test-via-url', '--include-ts'], + testOptions: { captureLogs: true }, + cliOptions: { upgradeTaskUrl: `${projectPath}/upgrade/index.js` }, + }, + ); + await backupOrRestoreSource(); + await start(); + + const pkgA = await readSource('packages/pkg-a/file.js'); + const pkgAts = await readSource('packages/pkg-a/tsfile.ts'); + const pkgB = await readSource('packages/pkg-b/file.js'); + const pkgC = await readSource('packages/pkg-c/file.js'); + const pkgD = await readSource('not-workspace/pkg-d/file.js'); + + await restoreSource(); + + expect(pkgA).to.equal('export const updated = true;'); + expect(pkgAts).to.equal('export const updated = true'); + expect(pkgB).to.equal('export const updated = true;'); + expect(pkgC).to.equal('export const updated = false;'); + expect(pkgD).to.equal('export const updated = false;'); + }); + + it('works when monoroot has dep, but child has not', async () => { + const monoRepo = { + 'upgrade/index.mjs': ` + import { executeJsCodeShiftTransforms } from '../../../../src/migrate-helpers/executeJsCodeShiftTransforms.js'; + import { verifyPackageJson } from '../../../../src/migrate-helpers/verifyPackageJson.js'; + + export async function upgrade({ inputDir, jscsOpts }, workspaceMeta) { + await verifyPackageJson(inputDir, { + depsToCheck: [{ name: 'dep-foo', minVersion: '2.0.0' }], + monoRoot: workspaceMeta.monoRoot, + }); + + await executeJsCodeShiftTransforms( + inputDir, + new URL('./jscodeshift/', import.meta.url), + {...jscsOpts, includeTs: true}, + { workspaceMeta }, + ); + } + + export const _mockable = { upgrade }; + `, + 'upgrade/jscodeshift/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + 'package.json': JSON.stringify({ + name: 'mono-root', + devDependencies: { 'dep-foo': '2.0.0' }, + workspaces: ['packages/*'], + }), + // is considered, bc mono has dep + 'packages/pkg-a/package.json': JSON.stringify({ + name: 'pkg-a', + }), + 'packages/pkg-a/file.js': ['export const updated = false'].join('\n'), + 'packages/pkg-a/tsfile.ts': ['export const updated = false'].join('\n'), + // is considered, bc (dev)Dep (and mono has dep) + 'packages/pkg-b/package.json': JSON.stringify({ + name: 'pkg-b', + devDependencies: { 'dep-foo': '2.0.0' }, + }), + 'packages/pkg-b/file.js': ['export const updated = false'].join('\n'), + // is considered, bc mono has dep + 'not-workspace/pkg-dpackage.json': JSON.stringify({ + name: 'pkg-d', + }), + 'not-workspace/pkg-d/file.js': ['export const updated = false'].join('\n'), + }; + + const projectPath = await createTempProjectFixture(monoRepo, { + projectName: 'monoRepo2', + }); + + const { start, backupOrRestoreSource, restoreSource, readSource } = await setupTestCli( + projectPath, + { + cliArgv: ['upgrade', '-t', '_test-via-url', '--include-ts'], + testOptions: { captureLogs: true }, + cliOptions: { upgradeTaskUrl: `${projectPath}/upgrade/index.mjs` }, + }, + ); + await backupOrRestoreSource(); + await start(); + + const pkgA = await readSource('packages/pkg-a/file.js'); + const pkgAts = await readSource('packages/pkg-a/tsfile.ts'); + const pkgB = await readSource('packages/pkg-b/file.js'); + const pkgD = await readSource('not-workspace/pkg-d/file.js'); + + await restoreSource(); + + expect(pkgA).to.equal('export const updated = true;'); + expect(pkgAts).to.equal('export const updated = true'); + expect(pkgB).to.equal('export const updated = true;'); + expect(pkgD).to.equal('export const updated = true;'); + }); + + it('works with typescript files when includeTs is passed', async () => { + const monoRepo = { + 'upgrade/index.mjs': ` + import { executeJsCodeShiftTransforms } from '../../../../src/migrate-helpers/executeJsCodeShiftTransforms.js'; + import { verifyPackageJson } from '../../../../src/migrate-helpers/verifyPackageJson.js'; + + export async function upgrade({ inputDir, jscsOpts }, workspaceMeta) { + await verifyPackageJson(inputDir, { + depsToCheck: [{ name: 'dep-foo', minVersion: '2.0.0' }], + monoRoot: workspaceMeta.monoRoot, + }); + + await executeJsCodeShiftTransforms( + inputDir, + new URL('./jscodeshift/', import.meta.url), + {...jscsOpts, includeTs: true}, + { workspaceMeta }, + ); + } + + export const _mockable = { upgrade }; + `, + 'upgrade/jscodeshift/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + 'package.json': JSON.stringify({ + name: 'mono-root', + devDependencies: { 'dep-foo': '2.0.0' }, + workspaces: ['packages/*'], + }), + // is considered, bc mono has dep + 'packages/pkg-a/package.json': JSON.stringify({ + name: 'pkg-a', + }), + 'packages/pkg-a/file.ts': ['export const updated = false'].join('\n'), + // is considered, bc (dev)Dep (and mono has dep) + 'packages/pkg-b/package.json': JSON.stringify({ + name: 'pkg-b', + devDependencies: { 'dep-foo': '2.0.0' }, + }), + 'packages/pkg-b/file.ts': ['export const updated = false'].join('\n'), + }; + + const projectPath = await createTempProjectFixture(monoRepo, { + projectName: 'monoRepo3', + }); + + const { start, backupOrRestoreSource, restoreSource, readSource } = await setupTestCli( + projectPath, + { + cliArgv: ['upgrade', '-t', '_test-via-url', '--include-ts'], + testOptions: { captureLogs: true }, + cliOptions: { upgradeTaskUrl: `${projectPath}/upgrade/index.mjs` }, + }, + ); + await backupOrRestoreSource(); + await start(); + + const pkgA = await readSource('packages/pkg-a/file.ts'); + const pkgB = await readSource('packages/pkg-b/file.ts'); + + await restoreSource(); + + expect(pkgA).to.equal('export const updated = true'); + expect(pkgB).to.equal('export const updated = true'); + }); + + it('does not work with typescript files when includeTs is not passed', async () => { + const monoRepo = { + 'upgrade/index.mjs': ` + import { executeJsCodeShiftTransforms } from '../../../../src/migrate-helpers/executeJsCodeShiftTransforms.js'; + import { verifyPackageJson } from '../../../../src/migrate-helpers/verifyPackageJson.js'; + + export async function upgrade({ inputDir, jscsOpts }, workspaceMeta) { + await verifyPackageJson(inputDir, { + depsToCheck: [{ name: 'dep-foo', minVersion: '2.0.0' }], + monoRoot: workspaceMeta.monoRoot, + }); + + await executeJsCodeShiftTransforms( + inputDir, + new URL('./jscodeshift/', import.meta.url), + // no includeTs + {...jscsOpts }, + { workspaceMeta }, + ); + } + + export const _mockable = { upgrade }; + `, + 'upgrade/jscodeshift/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + 'package.json': JSON.stringify({ + name: 'mono-root', + devDependencies: { 'dep-foo': '2.0.0' }, + workspaces: ['packages/*'], + }), + // is considered, bc mono has dep + 'packages/pkg-a/package.json': JSON.stringify({ + name: 'pkg-a', + }), + 'packages/pkg-a/file.ts': ['export const updated = false'].join('\n'), + // is considered, bc (dev)Dep (and mono has dep) + 'packages/pkg-b/package.json': JSON.stringify({ + name: 'pkg-b', + devDependencies: { 'dep-foo': '2.0.0' }, + }), + 'packages/pkg-b/file.ts': ['export const updated = false'].join('\n'), + }; + + const projectPath = await createTempProjectFixture(monoRepo, { + projectName: 'monoRepo4', + }); + + const { start, backupOrRestoreSource, restoreSource, readSource } = await setupTestCli( + projectPath, + { + cliArgv: ['upgrade', '-t', '_test-via-url'], + testOptions: { captureLogs: true }, + cliOptions: { upgradeTaskUrl: `${projectPath}/upgrade/index.mjs` }, + }, + ); + await backupOrRestoreSource(); + await start(); + + const pkgA = await readSource('packages/pkg-a/file.ts'); + const pkgB = await readSource('packages/pkg-b/file.ts'); + + await restoreSource(); + + expect(pkgA).to.equal('export const updated = false'); + expect(pkgB).to.equal('export const updated = false'); + }); +}); diff --git a/packages-node/migrate-cli/test/commands/UpgradeCommandBase.test.js b/packages-node/migrate-cli/test/commands/UpgradeCommandBase.test.js new file mode 100644 index 0000000000..b3a9d556da --- /dev/null +++ b/packages-node/migrate-cli/test/commands/UpgradeCommandBase.test.js @@ -0,0 +1,163 @@ +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { Command } from 'commander'; +import path from 'path'; +import sinon from 'sinon'; +import fs from 'fs'; +import { _mockable, UpgradeCommandBase } from '../../src/commands/UpgradeCommandBase.js'; +import { MigrateCli } from '../../src/MigrateCli.js'; + +chai.use(chaiAsPromised); +const { expect } = chai; + +describe('UpgradeCommandBase works as base command', () => { + describe('initialisation of the command works as expected', () => { + const upgradeCommandBase = new UpgradeCommandBase(); + it('sets initial values correctly', () => { + expect(upgradeCommandBase.upgradesConfig).to.not.be.null; + }); + + it('sets up the command', async () => { + const addHelpTextSpy = sinon.spy(upgradeCommandBase, 'addHelpText'); + const setCommandOptionsSpy = sinon.spy(upgradeCommandBase, 'setCommandOptions'); + let commandAdded = false; + const program = new Command(); + // @ts-ignore + program.addCommand = () => { + commandAdded = true; + }; + await upgradeCommandBase.setupCommand(program, {}); + expect(addHelpTextSpy.callCount).to.equal(1); + expect(setCommandOptionsSpy.callCount).to.equal(1); + expect(commandAdded).to.be.true; + addHelpTextSpy.resetHistory(); + setCommandOptionsSpy.resetHistory(); + }); + }); + + describe('upgrade task behaves as expected', () => { + let upgradeCommandBase; + beforeEach(() => { + upgradeCommandBase = new UpgradeCommandBase(); + sinon.restore(); + upgradeCommandBase.cli = new MigrateCli(); + upgradeCommandBase.cli.options.task = 'lib-foo-1-to-2'; + }); + + it('fails when no task is provided', async () => { + upgradeCommandBase.cli.options.task = undefined; + try { + await upgradeCommandBase.upgrade(); + } catch (e) { + expect(e.message).to.equal(`Please provide a task via -t`); + } + }); + + it('fails when setTransformOptions is not overridden', async () => { + try { + await upgradeCommandBase.upgrade(); + } catch (e) { + expect(e.message).to.contain(`The Upgrade Command is not properly configured`); + } + }); + + it('succeeds when upgradeTaskUrl is explicitly set', async () => { + const fsExistsStub = sinon.stub(fs, 'existsSync'); + sinon.stub(_mockable, 'runUpgradeTask'); + fsExistsStub.onFirstCall().returns(false); + fsExistsStub.onSecondCall().returns(true); + upgradeCommandBase.cli.options.upgradeTaskUrl = 'test'; + await upgradeCommandBase.upgrade(); + }); + + it('succeeds when upgradesDir is explicitly set', async () => { + const fsExistsStub = sinon.stub(fs, 'existsSync'); + sinon.stub(_mockable, 'runUpgradeTask'); + fsExistsStub.returns(false); + upgradeCommandBase.cli.options.upgradesDir = 'http://www.example.com'; + await upgradeCommandBase.upgrade(); + }); + }); + + describe('composite tasks are allowed', () => { + let upgradeCommandBase; + + beforeEach(() => { + upgradeCommandBase = new UpgradeCommandBase(); + sinon.restore(); + upgradeCommandBase.cli = new MigrateCli(); + upgradeCommandBase.cli.options.task = 'transform-foo-combined'; + upgradeCommandBase.cli.options.upgradesDir = 'http://www.example.com'; + }); + + it('runs upgrade for multiple tasks if found', async () => { + const allowedCompositeTasks = new Map(); + allowedCompositeTasks.set('transform-foo-combined', [ + 'transform-foo-part-1', + 'transform-foo-part-2', + ]); + upgradeCommandBase.cli.options.allowedCompositeTasks = allowedCompositeTasks; + const runUpgradeStub = sinon.stub(_mockable, 'runUpgradeTask'); + const readDirStub = sinon.stub(fs, 'readdirSync'); + readDirStub.returns(['transform-foo-part-1', 'transform-foo-part-2']); + await upgradeCommandBase.upgrade(); + expect(runUpgradeStub.callCount).to.equal(2); + }); + + it('does not run upgrade for multiple tasks if one not found', async () => { + const allowedCompositeTasks = new Map(); + allowedCompositeTasks.set('transform-foo-combined', [ + 'transform-foo-part-1', + 'transform-foo-part-2', + 'transform-foo-part-3', + ]); + upgradeCommandBase.cli.options.allowedCompositeTasks = allowedCompositeTasks; + const runUpgradeStub = sinon.stub(_mockable, 'runUpgradeTask'); + const readDirStub = sinon.stub(fs, 'readdirSync'); + readDirStub.returns(['transform-foo-part-1', 'transform-foo-part-2']); + await upgradeCommandBase.upgrade(); + expect(runUpgradeStub.callCount).to.equal(0); + }); + + it('does run upgrade for multiple tasks if task dir has more tasks than required', async () => { + const allowedCompositeTasks = new Map(); + allowedCompositeTasks.set('transform-foo-combined', [ + 'transform-foo-part-1', + 'transform-foo-part-2', + ]); + upgradeCommandBase.cli.options.allowedCompositeTasks = allowedCompositeTasks; + const runUpgradeStub = sinon.stub(_mockable, 'runUpgradeTask'); + const readDirStub = sinon.stub(fs, 'readdirSync'); + readDirStub.returns(['transform-foo-part-1', 'transform-foo-part-2', 'transform-irrelevant']); + await upgradeCommandBase.upgrade(); + expect(runUpgradeStub.callCount).to.equal(2); + }); + }); + + describe('getUpgradesDirUrl works as expected with different inputs', () => { + it('handles a URL object', () => { + const input = new URL('https://www.example.com'); + const returned = _mockable.getUpgradesDirUrl(input); + expect(input.href).to.equal(returned.href); + }); + + it('handles string URL correctly', () => { + const input = 'https://www.example.com/'; + const returned = _mockable.getUpgradesDirUrl(input); + expect(input).to.equal(returned.href); + }); + + it('handles a local absolute path correctly', () => { + const input = '/some/random/path'; + const returned = _mockable.getUpgradesDirUrl(input); + expect(returned.href).to.equal(`file://${input}`); + }); + + it('handles a local relative path correctly', () => { + const input = './some/random/path'; + const returned = _mockable.getUpgradesDirUrl(input, process.cwd()); + const resolvedPath = path.resolve(input); + expect(returned.href).to.equal(`file://${resolvedPath}`); + }); + }); +}); diff --git a/packages-node/migrate-cli/test/migrate-helpers/executeJsCodeShiftTransforms.test.js b/packages-node/migrate-cli/test/migrate-helpers/executeJsCodeShiftTransforms.test.js new file mode 100644 index 0000000000..3c5cb16d9e --- /dev/null +++ b/packages-node/migrate-cli/test/migrate-helpers/executeJsCodeShiftTransforms.test.js @@ -0,0 +1,233 @@ +import { expect } from 'chai'; +import path from 'path'; +import { pathToFileURL } from 'url'; +import { writeFile, readFile, mkdir } from 'fs/promises'; +import { executeJsCodeShiftTransforms } from '../../src/migrate-helpers/executeJsCodeShiftTransforms.js'; +import { + createTempProjectFixture, + restoreTempProjectFixture, +} from '../../test-helpers/mock-helpers.js'; + +describe('executeJsCodeShiftTransforms', () => { + after(() => { + restoreTempProjectFixture(); + }); + + it('logs only a summary at the end', async () => { + /** + * @type {string[]} + */ + const logs = []; + const originalLog = console.log; + console.log = msg => { + logs.push(msg); + }; + const fixture = './fixtures/02a-executeJsCodeShiftTransforms-success/'; + + await mkdir(new URL(`${fixture}src/`, import.meta.url), { recursive: true }); + await writeFile( + new URL(`${fixture}src/index.js`, import.meta.url), + `export const updated = false;`, + ); + await writeFile( + new URL(`${fixture}src/another.js`, import.meta.url), + `export const updated = false;`, + ); + + const originalContent1 = await readFile( + new URL(`${fixture}src/index.js`, import.meta.url), + 'utf8', + ); + const originalContent2 = await readFile( + new URL(`${fixture}src/another.js`, import.meta.url), + 'utf8', + ); + + await executeJsCodeShiftTransforms( + new URL(`${fixture}src`, import.meta.url), + new URL(`${fixture}transforms`, import.meta.url), + ); + + const transformedContent1 = await readFile( + new URL(`${fixture}src/index.js`, import.meta.url), + 'utf8', + ); + const transformedContent2 = await readFile( + new URL(`${fixture}src/another.js`, import.meta.url), + 'utf8', + ); + + // restore content + await writeFile(new URL(`${fixture}src/index.js`, import.meta.url), originalContent1); + await writeFile(new URL(`${fixture}src/another.js`, import.meta.url), originalContent2); + + expect(transformedContent1).to.equal('export const updated = true;'); + expect(transformedContent2).to.equal('export const updated = true;'); + + expect(logs).to.include('🔎 Found 2 files to transform'); + expect(logs).to.include('🚀 Running jscodeshift mod "write"'); + expect(logs).to.include('✅ 2 files got updated successfully.'); + + console.log = originalLog; + }); + + it('supports mdjs (.md|.mdx) files as well', async () => { + const projMockWithStringifiedJson = { + 'transforms/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return \`export const filePath = '\${file.path}';\n\`; + };`, + 'src/code/index.js': `export const updated = false;`, + 'src/stories/index.md': [ + '# Title\n\nParagraph\n', + '```js', + 'export const updated = false;', + '```', + '\n## Second Title\n\nParagraph\n', + '```js', + 'export const updated2 = false;', + '```', + ].join('\n'), + 'src/stories2/index.mdx': [ + '# Title2\n\nParagraph\n', + '```js', + 'export const updated = false;', + '```', + '\n## Second Title2\n\nParagraph\n', + '```js', + 'export const updated2 = false;', + '```', + ].join('\n'), + }; + + const projectPath = await createTempProjectFixture(projMockWithStringifiedJson, { + projectName: 'proj-with-md-files', + }); + + await executeJsCodeShiftTransforms( + new URL(pathToFileURL(`${projectPath}/src`), import.meta.url), + new URL(pathToFileURL(`${projectPath}/transforms`), import.meta.url), + ); + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/src/stories/index.md`), import.meta.url), + 'utf8', + ), + ).to.equal( + [ + '# Title\n\nParagraph\n', + '```js', + `export const filePath = '${process.cwd()}${path.sep}_tmp-md-blocks${path.sep}h-549707620-index-0.js';`, + '```', + '\n## Second Title\n\nParagraph\n', + '```js', + `export const filePath = '${process.cwd()}${path.sep}_tmp-md-blocks${path.sep}h-549707620-index-1.js';`, + '```', + ].join('\n'), + ); + + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/src/stories2/index.mdx`), import.meta.url), + 'utf8', + ), + ).to.equal( + [ + '# Title2\n\nParagraph\n', + '```js', + `export const filePath = '${process.cwd()}${path.sep}_tmp-md-blocks${path.sep}h1054506434-index-0.js';`, + '```', + '\n## Second Title2\n\nParagraph\n', + '```js', + `export const filePath = '${process.cwd()}${path.sep}_tmp-md-blocks${path.sep}h1054506434-index-1.js';`, + '```', + ].join('\n'), + ); + }); + + it('also works with hidden .storybook folder', async () => { + const projMockWithStringifiedJson = { + 'transforms/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + '.storybook/index.js': `export const updated = false;`, + '.storybook/index.md': [ + '# Title\n\nParagraph\n', + '```js', + 'export const updated = false```', + '\n## Second Title\n\nParagraph\n', + '```js', + 'export const updated = false;```', + ].join('\n'), + }; + + const projectPath = await createTempProjectFixture(projMockWithStringifiedJson, { + projectName: 'proj-with-hidden-storybook-folder', + }); + + await executeJsCodeShiftTransforms( + new URL(pathToFileURL(`${projectPath}/.storybook`), import.meta.url), + new URL(pathToFileURL(`${projectPath}/transforms`), import.meta.url), + ); + + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/.storybook/index.js`), import.meta.url), + 'utf8', + ), + ).to.equal('export const updated = true'); + + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/.storybook/index.md`), import.meta.url), + 'utf8', + ), + ).to.equal( + [ + '# Title\n\nParagraph\n', + '```js', + 'export const updated = true```', + '\n## Second Title\n\nParagraph\n', + '```js', + 'export const updated = true```', + ].join('\n'), + ); + }); + + it("does not work with .md files containing ['CHANGELOG', 'README', 'CONTRIBUTING', 'MIGRATION']", async () => { + const projMockWithStringifiedJson = { + 'transforms/write_-_cjs-export.cjs': `module.exports = async function transformerWrapper(file, api, options) { + return 'export const updated = true'; + };`, + 'src/my-CHANGELOG-x.md': '```js\nexport const updated = false;\n```', + 'src/my-README-x.md': '```js\nexport const updated = false;\n```', + 'src/my-CONTRIBUTING-x.md': '```js\nexport const updated = false;\n```', + 'src/my-MIGRATION-x.md': '```js\nexport const updated = false;\n```', + 'src/my-updated-x.js': `export const updated = false;`, + }; + + const projectPath = await createTempProjectFixture(projMockWithStringifiedJson, { + projectName: 'proj-with-reserved-md-filenames', + }); + + await executeJsCodeShiftTransforms( + new URL(pathToFileURL(`${projectPath}/src`), import.meta.url), + new URL(pathToFileURL(`${projectPath}/transforms`), import.meta.url), + ); + + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/src/my-updated-x.js`), import.meta.url), + 'utf8', + ), + ).to.equal('export const updated = true'); + + for (const fileNameInclude of ['CHANGELOG', 'README', 'CONTRIBUTING', 'MIGRATION']) { + expect( + await readFile( + new URL(pathToFileURL(`${projectPath}/src/my-${fileNameInclude}-x.md`), import.meta.url), + 'utf8', + ), + ).to.equal('```js\nexport const updated = false;\n```'); + } + }); +}); diff --git a/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/another.js b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/another.js new file mode 100644 index 0000000000..368ff4ee91 --- /dev/null +++ b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/another.js @@ -0,0 +1 @@ +export const updated = false; diff --git a/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/index.js b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/index.js new file mode 100644 index 0000000000..368ff4ee91 --- /dev/null +++ b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/src/index.js @@ -0,0 +1 @@ +export const updated = false; diff --git a/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/transforms/write_-_cjs-export.cjs b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/transforms/write_-_cjs-export.cjs new file mode 100644 index 0000000000..3834a81313 --- /dev/null +++ b/packages-node/migrate-cli/test/migrate-helpers/fixtures/02a-executeJsCodeShiftTransforms-success/transforms/write_-_cjs-export.cjs @@ -0,0 +1,3 @@ +module.exports = async function transformerWrapper(/* fileInfo, api, options */) { + return 'export const updated = true;'; +}; diff --git a/packages-node/migrate-cli/test/mocks/commands/MockCommand.js b/packages-node/migrate-cli/test/mocks/commands/MockCommand.js new file mode 100644 index 0000000000..20b1af0e5b --- /dev/null +++ b/packages-node/migrate-cli/test/mocks/commands/MockCommand.js @@ -0,0 +1,15 @@ +/* eslint-disable */ +import { Command } from 'commander'; + +export class MockCommand { + async setupCommand(program, cli) { + this.cli = cli; + this.program = program; + this.active = true; + const command = new Command('mock'); + command.action(async options => { + cli.activePlugin = this; + }); + this.program.addCommand(command); + } +} diff --git a/packages-node/migrate-cli/test/mocks/config-file-1.js b/packages-node/migrate-cli/test/mocks/config-file-1.js new file mode 100644 index 0000000000..8b29819ffa --- /dev/null +++ b/packages-node/migrate-cli/test/mocks/config-file-1.js @@ -0,0 +1,4 @@ +export default { + inputDir: 'otherInputDir', + upgradesDir: 'otherUpgradesDir', +}; diff --git a/packages-node/migrate-cli/tsconfig.json b/packages-node/migrate-cli/tsconfig.json new file mode 100644 index 0000000000..c2bef97cf1 --- /dev/null +++ b/packages-node/migrate-cli/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist-types", + "rootDir": "." + }, + "include": ["src/**/*.js", "types"], + "exclude": ["dist-types"] +} diff --git a/packages-node/migrate-cli/types/index.ts b/packages-node/migrate-cli/types/index.ts new file mode 100644 index 0000000000..4f2cbadf2f --- /dev/null +++ b/packages-node/migrate-cli/types/index.ts @@ -0,0 +1,39 @@ +export type WorkspaceMeta = { + /** Path to monorepo root */ + monoRoot: string; + /** Whether we're dealing with the monorepo root, a workspace, or a regular single package repo */ + type: 'monorepo-workspace' | 'monorepo-root' | 'single-package'; + /** All packages within the monorepo and their types */ + workspacePackages: { + dir: string; + type: 'monorepo-workspace' | 'monorepo-root' | 'single-package'; + }[]; +}; + +export type Options = { + configFile?: string; + inputDir: string; + cwd: string; + setupCliPlugins?: Function; + task?: string; + jscsOpts?: object; + upgradesConfigHref?: string; + upgradesDir: URL | string; + _upgradesDirUrl?: URL | undefined; + upgradeTaskNames: string[]; + upgradeTaskUrl: string | URL; + allowedCompositeTasks?: Map; +}; + +export type InitOptions = { + plugins?: { setupCommand: Function; stop: Function }[]; + argv?: string[]; + commandsUrls?: URL[]; + cliName?: string; + cliIntroductionText?: string; + includeBaseCommands?: boolean; + cwd?: string; + pathToPkgJson?: string; + cliVersion?: string; + options?: Partial; +}; diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-classes_-_importing-target-project_0.0.2-target-mock__-1281497701.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-classes_-_importing-target-project_0.0.2-target-mock__-1281497701.json new file mode 100644 index 0000000000..1337fbfbb4 --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-classes_-_importing-target-project_0.0.2-target-mock__-1281497701.json @@ -0,0 +1,220 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "find-classes", + "requiredAst": "oxc", + "identifier": "importing-target-project_0.0.2-target-mock__-1281497701", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "gatherFilesConfig": {}, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "file": "./target-src/find-customelements/multiple.js", + "result": [ + { + "name": null, + "isMixin": true, + "superClasses": [ + { + "name": "HTMLElement", + "isMixin": false, + "rootFile": { + "file": "[current]", + "specifier": "HTMLElement" + } + } + ], + "members": { + "props": [], + "methods": [] + } + }, + { + "name": "ExtendedOnTheFly", + "isMixin": false, + "superClasses": [ + { + "isMixin": true, + "rootFile": { + "file": "[current]" + } + }, + { + "isMixin": false, + "rootFile": { + "file": "[current]" + } + } + ], + "members": { + "props": [], + "methods": [] + } + } + ] + }, + { + "file": "./target-src/match-subclasses/ExtendedComp.js", + "result": [ + { + "name": "ExtendedComp", + "isMixin": false, + "superClasses": [ + { + "name": "MyCompMixin", + "isMixin": true, + "rootFile": { + "file": "exporting-ref-project", + "specifier": "[default]" + } + }, + { + "name": "RefClass", + "isMixin": false, + "rootFile": { + "file": "exporting-ref-project", + "specifier": "RefClass" + } + } + ], + "members": { + "props": [ + { + "name": "getterSetter", + "accessType": "public", + "kind": [ + "get", + "set" + ] + }, + { + "name": "staticGetterSetter", + "accessType": "public", + "static": true, + "kind": [ + "get", + "set" + ] + }, + { + "name": "attributes", + "accessType": "public", + "static": true, + "kind": [ + "get" + ] + }, + { + "name": "styles", + "accessType": "public", + "static": true, + "kind": [ + "get" + ] + }, + { + "name": "updateComplete", + "accessType": "public", + "kind": [ + "get" + ] + }, + { + "name": "localizeNamespaces", + "accessType": "public", + "static": true, + "kind": [ + "get" + ] + }, + { + "name": "slots", + "accessType": "public", + "kind": [ + "get" + ] + } + ], + "methods": [ + { + "name": "method", + "accessType": "public" + }, + { + "name": "_protectedMethod", + "accessType": "protected" + }, + { + "name": "__privateMethod", + "accessType": "private" + }, + { + "name": "$protectedMethod", + "accessType": "protected" + }, + { + "name": "$$privateMethod", + "accessType": "private" + }, + { + "name": "constructor", + "accessType": "public" + }, + { + "name": "connectedCallback", + "accessType": "public" + }, + { + "name": "disconnectedCallback", + "accessType": "public" + }, + { + "name": "requestUpdate", + "accessType": "public" + }, + { + "name": "createRenderRoot", + "accessType": "public" + }, + { + "name": "render", + "accessType": "public" + }, + { + "name": "updated", + "accessType": "public" + }, + { + "name": "firstUpdated", + "accessType": "public" + }, + { + "name": "update", + "accessType": "public" + }, + { + "name": "shouldUpdate", + "accessType": "public" + }, + { + "name": "onLocaleUpdated", + "accessType": "public" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-customelements_-_importing-target-project_0.0.2-target-mock__983214811.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-customelements_-_importing-target-project_0.0.2-target-mock__983214811.json new file mode 100644 index 0000000000..ba8ae9e665 --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-customelements_-_importing-target-project_0.0.2-target-mock__983214811.json @@ -0,0 +1,52 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "find-customelements", + "requiredAst": "oxc", + "identifier": "importing-target-project_0.0.2-target-mock__983214811", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "gatherFilesConfig": {}, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "file": "./target-src/find-customelements/multiple.js", + "result": [ + { + "tagName": "ref-class", + "constructorIdentifier": "RefClass", + "rootFile": { + "file": "exporting-ref-project", + "specifier": "RefClass" + } + }, + { + "tagName": "extended-comp", + "constructorIdentifier": "ExtendedComp", + "rootFile": { + "file": "./target-src/match-subclasses/ExtendedComp.js", + "specifier": "ExtendedComp" + } + }, + { + "tagName": "on-the-fly", + "constructorIdentifier": "[inline]", + "rootFile": { + "file": "[current]", + "specifier": "[inline]" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-exports_-_exporting-ref-project_1.0.0__-882566805.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-exports_-_exporting-ref-project_1.0.0__-882566805.json new file mode 100644 index 0000000000..dd490f9624 --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-exports_-_exporting-ref-project_1.0.0__-882566805.json @@ -0,0 +1,194 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "find-exports", + "requiredAst": "oxc", + "identifier": "exporting-ref-project_1.0.0__-882566805", + "targetProject": { + "mainEntry": "./index.js", + "name": "exporting-ref-project", + "version": "1.0.0", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "skipFileImports": false, + "gatherFilesConfig": {}, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "file": "./index.js", + "result": [ + { + "exportSpecifiers": [ + "[default]" + ], + "source": "./ref-src/core.js", + "normalizedSource": "./ref-src/core.js", + "rootFileMap": [ + { + "currentFileSpecifier": "[default]", + "rootFile": { + "file": "./ref-src/core.js", + "specifier": "[default]" + } + } + ] + }, + { + "exportSpecifiers": [ + "RefClass", + "RefRenamedClass" + ], + "localMap": [ + { + "local": "RefClass", + "exported": "RefRenamedClass" + } + ], + "source": "./ref-src/core.js", + "normalizedSource": "./ref-src/core.js", + "rootFileMap": [ + { + "currentFileSpecifier": "RefClass", + "rootFile": { + "file": "./ref-src/core.js", + "specifier": "RefClass" + } + }, + { + "currentFileSpecifier": "RefRenamedClass", + "rootFile": { + "file": "./ref-src/core.js", + "specifier": "RefClass" + } + } + ] + }, + { + "exportSpecifiers": [ + "[file]" + ], + "rootFileMap": [ + null + ] + } + ] + }, + { + "file": "./not-imported.js", + "result": [ + { + "exportSpecifiers": [ + "notImported" + ], + "localMap": [], + "rootFileMap": [ + { + "currentFileSpecifier": "notImported", + "rootFile": { + "file": "[current]", + "specifier": "notImported" + } + } + ] + }, + { + "exportSpecifiers": [ + "[file]" + ], + "rootFileMap": [ + null + ] + } + ] + }, + { + "file": "./ref-component.js", + "result": [ + { + "exportSpecifiers": [ + "[file]" + ], + "rootFileMap": [ + null + ] + } + ] + }, + { + "file": "./ref-src/core.js", + "result": [ + { + "exportSpecifiers": [ + "RefClass" + ], + "localMap": [], + "rootFileMap": [ + { + "currentFileSpecifier": "RefClass", + "rootFile": { + "file": "[current]", + "specifier": "RefClass" + } + } + ] + }, + { + "exportSpecifiers": [ + "[default]" + ], + "rootFileMap": [ + { + "currentFileSpecifier": "[default]", + "rootFile": { + "file": "[current]", + "specifier": "[default]" + } + } + ] + }, + { + "exportSpecifiers": [ + "[file]" + ], + "rootFileMap": [ + null + ] + } + ] + }, + { + "file": "./ref-src/folder/index.js", + "result": [ + { + "exportSpecifiers": [ + "resolvePathCorrect" + ], + "localMap": [], + "rootFileMap": [ + { + "currentFileSpecifier": "resolvePathCorrect", + "rootFile": { + "file": "[current]", + "specifier": "resolvePathCorrect" + } + } + ] + }, + { + "exportSpecifiers": [ + "[file]" + ], + "rootFileMap": [ + null + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-imports_-_importing-target-project_0.0.2-target-mock__728837360.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-imports_-_importing-target-project_0.0.2-target-mock__728837360.json new file mode 100644 index 0000000000..a161c2ef5e --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/find-imports_-_importing-target-project_0.0.2-target-mock__728837360.json @@ -0,0 +1,204 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "find-imports", + "requiredAst": "oxc", + "identifier": "importing-target-project_0.0.2-target-mock__728837360", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "keepInternalSources": false, + "gatherFilesConfig": {}, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "file": "./target-src/find-customelements/multiple.js", + "result": [ + { + "importSpecifiers": [ + "RefClass" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + } + ] + }, + { + "file": "./target-src/find-imports/all-notations.js", + "result": [ + { + "importSpecifiers": [ + "[file]" + ], + "source": "imported/source", + "normalizedSource": "imported/source" + }, + { + "importSpecifiers": [ + "[default]" + ], + "source": "imported/source-a", + "normalizedSource": "imported/source-a" + }, + { + "importSpecifiers": [ + "b" + ], + "source": "imported/source-b", + "normalizedSource": "imported/source-b" + }, + { + "importSpecifiers": [ + "c", + "d" + ], + "source": "imported/source-c", + "normalizedSource": "imported/source-c" + }, + { + "importSpecifiers": [ + "[default]", + "f", + "g" + ], + "source": "imported/source-d", + "normalizedSource": "imported/source-d" + }, + { + "importSpecifiers": [ + "[default]" + ], + "source": "my/source-e", + "normalizedSource": "my/source-e" + }, + { + "importSpecifiers": [ + "[default]" + ], + "source": "[variable]", + "normalizedSource": "[variable]" + }, + { + "importSpecifiers": [ + "[*]" + ], + "source": "imported/source-g", + "normalizedSource": "imported/source-g" + } + ] + }, + { + "file": "./target-src/match-imports/deep-imports.js", + "result": [ + { + "importSpecifiers": [ + "RefClass" + ], + "source": "exporting-ref-project/ref-src/core.js", + "normalizedSource": "exporting-ref-project/ref-src/core.js" + }, + { + "importSpecifiers": [ + "[default]" + ], + "source": "exporting-ref-project/ref-src/core.js", + "normalizedSource": "exporting-ref-project/ref-src/core.js" + }, + { + "importSpecifiers": [ + "nonMatched" + ], + "source": "unknown-project/xyz.js", + "normalizedSource": "unknown-project/xyz.js" + }, + { + "importSpecifiers": [ + "[file]" + ], + "source": "exporting-ref-project/ref-component", + "normalizedSource": "exporting-ref-project/ref-component" + }, + { + "importSpecifiers": [ + "resolvePathCorrect" + ], + "source": "exporting-ref-project/ref-src/folder", + "normalizedSource": "exporting-ref-project/ref-src/folder" + }, + { + "importSpecifiers": [ + "[*]" + ], + "source": "exporting-ref-project/ref-src/core.js", + "normalizedSource": "exporting-ref-project/ref-src/core.js" + } + ] + }, + { + "file": "./target-src/match-imports/root-level-imports.js", + "result": [ + { + "importSpecifiers": [ + "RefClass" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + }, + { + "importSpecifiers": [ + "RefRenamedClass" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + }, + { + "importSpecifiers": [ + "[default]" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + }, + { + "importSpecifiers": [ + "nonMatched" + ], + "source": "unknown-project", + "normalizedSource": "unknown-project" + } + ] + }, + { + "file": "./target-src/match-subclasses/ExtendedComp.js", + "result": [ + { + "importSpecifiers": [ + "RefClass" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + } + ] + }, + { + "file": "./target-src/match-subclasses/internalProxy.js", + "result": [ + { + "importSpecifiers": [ + "[default]" + ], + "source": "exporting-ref-project", + "normalizedSource": "exporting-ref-project" + } + ] + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-imports_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-18301594.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-imports_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-18301594.json new file mode 100644 index 0000000000..5e145ef83e --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-imports_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-18301594.json @@ -0,0 +1,162 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "match-imports", + "requiredAst": "oxc", + "identifier": "importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-18301594", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "referenceProject": { + "mainEntry": "./index.js", + "name": "exporting-ref-project", + "version": "1.0.0", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "gatherFilesConfig": {}, + "targetProjectResult": null, + "referenceProjectResult": null, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "exportSpecifier": { + "id": "[default]::./index.js::exporting-ref-project", + "name": "[default]", + "filePath": "./index.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/root-level-imports.js", + "./target-src/match-subclasses/internalProxy.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "RefClass::./index.js::exporting-ref-project", + "name": "RefClass", + "filePath": "./index.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/find-customelements/multiple.js", + "./target-src/match-imports/root-level-imports.js", + "./target-src/match-subclasses/ExtendedComp.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "RefRenamedClass::./index.js::exporting-ref-project", + "name": "RefRenamedClass", + "filePath": "./index.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/root-level-imports.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "[file]::./ref-component.js::exporting-ref-project", + "name": "[file]", + "filePath": "./ref-component.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/deep-imports.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "RefClass::./ref-src/core.js::exporting-ref-project", + "name": "RefClass", + "filePath": "./ref-src/core.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/deep-imports.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "[default]::./ref-src/core.js::exporting-ref-project", + "name": "[default]", + "filePath": "./ref-src/core.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/deep-imports.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "[file]::./ref-src/core.js::exporting-ref-project", + "name": "[file]", + "filePath": "./ref-src/core.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/deep-imports.js" + ] + } + ] + }, + { + "exportSpecifier": { + "id": "resolvePathCorrect::./ref-src/folder/index.js::exporting-ref-project", + "name": "resolvePathCorrect", + "filePath": "./ref-src/folder/index.js", + "project": "exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + "./target-src/match-imports/deep-imports.js" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-paths_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-1531951975.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-paths_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-1531951975.json new file mode 100644 index 0000000000..2662537982 --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-paths_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-1531951975.json @@ -0,0 +1,94 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "match-paths", + "requiredAst": "babel", + "identifier": "importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__-1531951975", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "referenceProject": { + "mainEntry": "./index.js", + "name": "exporting-ref-project", + "version": "1.0.0", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "gatherFilesConfig": {}, + "prefix": null, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "name": "[default]", + "variable": { + "from": "[default]", + "to": "ExtendedComp", + "paths": [ + { + "from": "./index.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "./ref-src/core.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "exporting-ref-project/index.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "exporting-ref-project/ref-src/core.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + } + ] + } + }, + { + "name": "RefClass", + "variable": { + "from": "RefClass", + "to": "ExtendedComp", + "paths": [ + { + "from": "./index.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "./ref-src/core.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "exporting-ref-project/index.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + }, + { + "from": "exporting-ref-project/ref-src/core.js", + "to": "./target-src/match-subclasses/ExtendedComp.js" + } + ] + }, + "tag": { + "from": "ref-component", + "to": "extended-comp", + "paths": [ + { + "from": "./ref-component.js", + "to": "./target-src/find-customelements/multiple.js" + }, + { + "from": "exporting-ref-project/ref-component.js", + "to": "./target-src/find-customelements/multiple.js" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-subclasses_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__119660402.json b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-subclasses_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__119660402.json new file mode 100644 index 0000000000..86439ca754 --- /dev/null +++ b/packages-node/providence-analytics/test-node/program/analyzers/e2e/match-subclasses_-_importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__119660402.json @@ -0,0 +1,67 @@ +{ + "meta": { + "searchType": "ast-analyzer", + "analyzerMeta": { + "name": "match-subclasses", + "requiredAst": "oxc", + "identifier": "importing-target-project_0.0.2-target-mock_+_exporting-ref-project_1.0.0__119660402", + "targetProject": { + "mainEntry": "./target-src/match-imports/root-level-imports.js", + "name": "importing-target-project", + "version": "0.0.2-target-mock", + "commitHash": "[not-a-git-root]" + }, + "referenceProject": { + "mainEntry": "./index.js", + "name": "exporting-ref-project", + "version": "1.0.0", + "commitHash": "[not-a-git-root]" + }, + "configuration": { + "gatherFilesConfig": {}, + "skipCheckMatchCompatibility": false, + "addSystemPathsInResult": false + } + } + }, + "queryOutput": [ + { + "exportSpecifier": { + "name": "[default]", + "project": "exporting-ref-project", + "filePath": "./index.js", + "id": "[default]::./index.js::exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + { + "file": "./target-src/match-subclasses/ExtendedComp.js", + "identifier": "ExtendedComp" + } + ] + } + ] + }, + { + "exportSpecifier": { + "name": "RefClass", + "project": "exporting-ref-project", + "filePath": "./index.js", + "id": "RefClass::./index.js::exporting-ref-project" + }, + "matchesPerProject": [ + { + "project": "importing-target-project", + "files": [ + { + "file": "./target-src/match-subclasses/ExtendedComp.js", + "identifier": "ExtendedComp" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/scripts/lint-versions.js b/scripts/lint-versions.js index c4914dd4ac..fa0487df74 100644 --- a/scripts/lint-versions.js +++ b/scripts/lint-versions.js @@ -54,6 +54,10 @@ function compareVersions(versionsA, versionsB) { if (dep === 'glob') { return; } + // commander will be removed from providence-analytics, resolving this conflict + if (dep === 'commander') { + return; + } if (versionsA[dep] && versionsB[dep] && versionsA[dep] !== versionsB[dep]) { if (!semver.satisfies(versionsA[dep], versionsB[dep])) { // if version doesn't satisfy range, check if they are both ranges,