diff --git a/.eslintrc.js b/.eslintrc.js index 5a1021119..d16dc3d0a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,6 +5,6 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ module.exports = { - extends: ['eslint-config-salesforce-typescript', 'eslint-config-salesforce-license', 'prettier'], + extends: ['eslint-config-salesforce-typescript', 'eslint-config-salesforce-license', 'prettier','plugin:sf-plugin/migration'], ignorePatterns: ['test/nuts/ebikes-lwc/**', 'test/nuts/nestedLWCProject/**'], }; diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc8f29c5d..d6392823e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,18 +22,18 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] command: - - 'yarn test:nuts:convert' - - 'yarn test:nuts:commands:other' - - 'yarn test:nuts:delete' - 'yarn test:nuts:deploy' - 'yarn test:nuts:deploy:async' + - 'yarn test:nuts:deploy:destructive' - 'yarn test:nuts:deploy:rest' - - 'yarn test:nuts:manifest:create' + - 'yarn test:nuts:mdapi' - 'yarn test:nuts:retrieve' - 'yarn test:nuts:specialTypes' - - 'yarn test:nuts:deploy:destructive' - 'yarn test:nuts:tracking' - - 'yarn test:nuts:mdapi' + - 'yarn test:nuts:deb' + exclude: + - os: windows-latest + command: yarn test:nuts:deb fail-fast: false with: os: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a403950..4c5c12d40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1286 +1,876 @@ # [2.8.0](https://github.com/salesforcecli/plugin-source/compare/2.7.0...2.8.0) (2023-03-15) - ### Features -* remove force:source:open command, now in plugin-org ([8c269db](https://github.com/salesforcecli/plugin-source/commit/8c269dbc755870eec4e7ac66b53604a818035f9f)) - - +- remove force:source:open command, now in plugin-org ([8c269db](https://github.com/salesforcecli/plugin-source/commit/8c269dbc755870eec4e7ac66b53604a818035f9f)) # [2.7.0](https://github.com/salesforcecli/plugin-source/compare/2.6.2...2.7.0) (2023-03-13) - ### Features -* verbose deploys without progress bar update with each poll ([#757](https://github.com/salesforcecli/plugin-source/issues/757)) ([0826a83](https://github.com/salesforcecli/plugin-source/commit/0826a83546952917de91f4b9a5a650e151d62aca)) +- verbose deploys without progress bar update with each poll ([#757](https://github.com/salesforcecli/plugin-source/issues/757)) ([0826a83](https://github.com/salesforcecli/plugin-source/commit/0826a83546952917de91f4b9a5a650e151d62aca)) +## [2.6.2](https://github.com/salesforcecli/plugin-source/compare/2.6.1...2.6.2) (2023-03-12) +### Bug Fixes -## [2.6.2](https://github.com/salesforcecli/plugin-source/compare/2.6.1...2.6.2) (2023-03-12) +- **deps:** bump @salesforce/source-tracking from 2.2.22 to 2.2.24 ([#764](https://github.com/salesforcecli/plugin-source/issues/764)) ([e493d9d](https://github.com/salesforcecli/plugin-source/commit/e493d9de576619fea9cd442639a707149425b69c)) +## [2.6.1](https://github.com/salesforcecli/plugin-source/compare/2.6.0...2.6.1) (2023-03-12) ### Bug Fixes -* **deps:** bump @salesforce/source-tracking from 2.2.22 to 2.2.24 ([#764](https://github.com/salesforcecli/plugin-source/issues/764)) ([e493d9d](https://github.com/salesforcecli/plugin-source/commit/e493d9de576619fea9cd442639a707149425b69c)) +- **deps:** bump @salesforce/source-deploy-retrieve from 7.11.0 to 7.11.3 ([#759](https://github.com/salesforcecli/plugin-source/issues/759)) ([14bdf84](https://github.com/salesforcecli/plugin-source/commit/14bdf845f36d8dd26de6b86916faad5cc29d1530)) +# [2.6.0](https://github.com/salesforcecli/plugin-source/compare/2.5.5...2.6.0) (2023-03-10) +### Features -## [2.6.1](https://github.com/salesforcecli/plugin-source/compare/2.6.0...2.6.1) (2023-03-12) +- get types from sdr registry ([e3df9ce](https://github.com/salesforcecli/plugin-source/commit/e3df9ced569ca6c2d1b4e4710caf7833b2663ea2)) +## [2.5.5](https://github.com/salesforcecli/plugin-source/compare/2.5.4...2.5.5) (2023-02-28) ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 7.11.0 to 7.11.3 ([#759](https://github.com/salesforcecli/plugin-source/issues/759)) ([14bdf84](https://github.com/salesforcecli/plugin-source/commit/14bdf845f36d8dd26de6b86916faad5cc29d1530)) +- **deps:** bump jsforce from 2.0.0-beta.19 to 2.0.0-beta.20 ([#745](https://github.com/salesforcecli/plugin-source/issues/745)) ([b637f68](https://github.com/salesforcecli/plugin-source/commit/b637f68cb3092ceae4f1bb65ddfc1fe67471ee31)) +## [2.5.4](https://github.com/salesforcecli/plugin-source/compare/2.5.3...2.5.4) (2023-02-18) +### Features -# [2.6.0](https://github.com/salesforcecli/plugin-source/compare/2.5.5...2.6.0) (2023-03-10) +- remove force:source:open command, now in plugin-org ([8c269db](https://github.com/salesforcecli/plugin-source/commit/8c269dbc755870eec4e7ac66b53604a818035f9f)) +# [2.7.0](https://github.com/salesforcecli/plugin-source/compare/2.6.2...2.7.0) (2023-03-13) ### Features -* get types from sdr registry ([e3df9ce](https://github.com/salesforcecli/plugin-source/commit/e3df9ced569ca6c2d1b4e4710caf7833b2663ea2)) +- verbose deploys without progress bar update with each poll ([#757](https://github.com/salesforcecli/plugin-source/issues/757)) ([0826a83](https://github.com/salesforcecli/plugin-source/commit/0826a83546952917de91f4b9a5a650e151d62aca)) +## [2.6.2](https://github.com/salesforcecli/plugin-source/compare/2.6.1...2.6.2) (2023-03-12) +### Bug Fixes -## [2.5.5](https://github.com/salesforcecli/plugin-source/compare/2.5.4...2.5.5) (2023-02-28) +- **deps:** bump @salesforce/source-tracking from 2.2.22 to 2.2.24 ([#764](https://github.com/salesforcecli/plugin-source/issues/764)) ([e493d9d](https://github.com/salesforcecli/plugin-source/commit/e493d9de576619fea9cd442639a707149425b69c)) +## [2.6.1](https://github.com/salesforcecli/plugin-source/compare/2.6.0...2.6.1) (2023-03-12) ### Bug Fixes -* **deps:** bump jsforce from 2.0.0-beta.19 to 2.0.0-beta.20 ([#745](https://github.com/salesforcecli/plugin-source/issues/745)) ([b637f68](https://github.com/salesforcecli/plugin-source/commit/b637f68cb3092ceae4f1bb65ddfc1fe67471ee31)) +- **deps:** bump @salesforce/source-deploy-retrieve from 7.11.0 to 7.11.3 ([#759](https://github.com/salesforcecli/plugin-source/issues/759)) ([14bdf84](https://github.com/salesforcecli/plugin-source/commit/14bdf845f36d8dd26de6b86916faad5cc29d1530)) +# [2.6.0](https://github.com/salesforcecli/plugin-source/compare/2.5.5...2.6.0) (2023-03-10) +### Features -## [2.5.4](https://github.com/salesforcecli/plugin-source/compare/2.5.3...2.5.4) (2023-02-18) +- get types from sdr registry ([e3df9ce](https://github.com/salesforcecli/plugin-source/commit/e3df9ced569ca6c2d1b4e4710caf7833b2663ea2)) +## [2.5.5](https://github.com/salesforcecli/plugin-source/compare/2.5.4...2.5.5) (2023-02-28) ### Bug Fixes -* **deps:** bump open from 8.4.0 to 8.4.1 ([#736](https://github.com/salesforcecli/plugin-source/issues/736)) ([d0e1f35](https://github.com/salesforcecli/plugin-source/commit/d0e1f3504b3b5d4ac51504881e52fec2dbd3fcea)) +- **deps:** bump jsforce from 2.0.0-beta.19 to 2.0.0-beta.20 ([#745](https://github.com/salesforcecli/plugin-source/issues/745)) ([b637f68](https://github.com/salesforcecli/plugin-source/commit/b637f68cb3092ceae4f1bb65ddfc1fe67471ee31)) +## [2.5.4](https://github.com/salesforcecli/plugin-source/compare/2.5.3...2.5.4) (2023-02-18) +### Bug Fixes -## [2.5.3](https://github.com/salesforcecli/plugin-source/compare/2.5.2...2.5.3) (2023-02-11) +- **deps:** bump open from 8.4.0 to 8.4.1 ([#736](https://github.com/salesforcecli/plugin-source/issues/736)) ([d0e1f35](https://github.com/salesforcecli/plugin-source/commit/d0e1f3504b3b5d4ac51504881e52fec2dbd3fcea)) +## [2.5.3](https://github.com/salesforcecli/plugin-source/compare/2.5.2...2.5.3) (2023-02-11) ### Bug Fixes -* **deps:** bump @salesforce/command from 5.2.35 to 5.3.0 ([#732](https://github.com/salesforcecli/plugin-source/issues/732)) ([657dbbb](https://github.com/salesforcecli/plugin-source/commit/657dbbb0afdb32a498694d8f0b112fb26206f7f7)) - - +- **deps:** bump @salesforce/command from 5.2.35 to 5.3.0 ([#732](https://github.com/salesforcecli/plugin-source/issues/732)) ([657dbbb](https://github.com/salesforcecli/plugin-source/commit/657dbbb0afdb32a498694d8f0b112fb26206f7f7)) ## [2.5.2](https://github.com/salesforcecli/plugin-source/compare/2.5.1...2.5.2) (2023-02-09) - ### Bug Fixes -* oclif topic description updates ([#706](https://github.com/salesforcecli/plugin-source/issues/706)) ([d925605](https://github.com/salesforcecli/plugin-source/commit/d9256055e7cd72a5ac1ad92f9459e7ec961e1048)) - - +- oclif topic description updates ([#706](https://github.com/salesforcecli/plugin-source/issues/706)) ([d925605](https://github.com/salesforcecli/plugin-source/commit/d9256055e7cd72a5ac1ad92f9459e7ec961e1048)) ## [2.5.1](https://github.com/salesforcecli/plugin-source/compare/2.5.0...2.5.1) (2023-02-09) - ### Bug Fixes -* enhance partial bundle delete tests for forceignored files ([#728](https://github.com/salesforcecli/plugin-source/issues/728)) ([0dc9bd2](https://github.com/salesforcecli/plugin-source/commit/0dc9bd2ce47691184fdca6040c6d3d93152bfe3f)) - - +- enhance partial bundle delete tests for forceignored files ([#728](https://github.com/salesforcecli/plugin-source/issues/728)) ([0dc9bd2](https://github.com/salesforcecli/plugin-source/commit/0dc9bd2ce47691184fdca6040c6d3d93152bfe3f)) # [2.5.0](https://github.com/salesforcecli/plugin-source/compare/2.4.3...2.5.0) (2023-02-08) - ### Features -* support for ExperiencePropertyType Bundle ([#727](https://github.com/salesforcecli/plugin-source/issues/727)) ([64d7059](https://github.com/salesforcecli/plugin-source/commit/64d70590f96d58d4a1589ecbbadb9bc5ad8848e3)) - - +- support for ExperiencePropertyType Bundle ([#727](https://github.com/salesforcecli/plugin-source/issues/727)) ([64d7059](https://github.com/salesforcecli/plugin-source/commit/64d70590f96d58d4a1589ecbbadb9bc5ad8848e3)) ## [2.4.3](https://github.com/salesforcecli/plugin-source/compare/2.4.2...2.4.3) (2023-02-03) - ### Bug Fixes -* **deps:** bump @oclif/core from 2.0.7 to 2.0.8 ([#715](https://github.com/salesforcecli/plugin-source/issues/715)) ([58da09b](https://github.com/salesforcecli/plugin-source/commit/58da09b14f38041a6e3be5e15a6d8062b4fd93fb)) - - +- **deps:** bump @oclif/core from 2.0.7 to 2.0.8 ([#715](https://github.com/salesforcecli/plugin-source/issues/715)) ([58da09b](https://github.com/salesforcecli/plugin-source/commit/58da09b14f38041a6e3be5e15a6d8062b4fd93fb)) ## [2.4.2](https://github.com/salesforcecli/plugin-source/compare/2.4.1...2.4.2) (2023-02-03) - ### Bug Fixes -* **deps:** bump http-cache-semantics from 4.1.0 to 4.1.1 ([#718](https://github.com/salesforcecli/plugin-source/issues/718)) ([78013fd](https://github.com/salesforcecli/plugin-source/commit/78013fd9369c70d7212970c933f2820deb81fd4f)) - - +- **deps:** bump http-cache-semantics from 4.1.0 to 4.1.1 ([#718](https://github.com/salesforcecli/plugin-source/issues/718)) ([78013fd](https://github.com/salesforcecli/plugin-source/commit/78013fd9369c70d7212970c933f2820deb81fd4f)) ## [2.4.1](https://github.com/salesforcecli/plugin-source/compare/2.4.0...2.4.1) (2023-02-03) - ### Bug Fixes -* nut for handling forceignored files for partial bundle deletes ([#716](https://github.com/salesforcecli/plugin-source/issues/716)) ([f95be35](https://github.com/salesforcecli/plugin-source/commit/f95be35f330e292c6f5a9cafbbac4dd684c2cf2c)) - - +- nut for handling forceignored files for partial bundle deletes ([#716](https://github.com/salesforcecli/plugin-source/issues/716)) ([f95be35](https://github.com/salesforcecli/plugin-source/commit/f95be35f330e292c6f5a9cafbbac4dd684c2cf2c)) # [2.4.0](https://github.com/salesforcecli/plugin-source/compare/2.3.16...2.4.0) (2023-02-01) - ### Features -* use latest oclif/core ([#714](https://github.com/salesforcecli/plugin-source/issues/714)) ([520f5d6](https://github.com/salesforcecli/plugin-source/commit/520f5d67bdf23e8d4236020b19f0f24c174bb48d)) - - +- use latest oclif/core ([#714](https://github.com/salesforcecli/plugin-source/issues/714)) ([520f5d6](https://github.com/salesforcecli/plugin-source/commit/520f5d67bdf23e8d4236020b19f0f24c174bb48d)) ## [2.3.16](https://github.com/salesforcecli/plugin-source/compare/2.3.15...2.3.16) (2023-01-20) - ### Bug Fixes -* only listen to events once per package ([#698](https://github.com/salesforcecli/plugin-source/issues/698)) ([b53510c](https://github.com/salesforcecli/plugin-source/commit/b53510cc3bf9fe1089c193112be847bb109aa1e2)) - - +- only listen to events once per package ([#698](https://github.com/salesforcecli/plugin-source/issues/698)) ([b53510c](https://github.com/salesforcecli/plugin-source/commit/b53510cc3bf9fe1089c193112be847bb109aa1e2)) ## [2.3.15](https://github.com/salesforcecli/plugin-source/compare/2.3.14...2.3.15) (2023-01-19) - ### Bug Fixes -* include deleted files in FileResponses for retrieves ([#683](https://github.com/salesforcecli/plugin-source/issues/683)) ([f1b0c64](https://github.com/salesforcecli/plugin-source/commit/f1b0c64a3ec75bba48e0a552e53a78af5a4d9251)) - - +- include deleted files in FileResponses for retrieves ([#683](https://github.com/salesforcecli/plugin-source/issues/683)) ([f1b0c64](https://github.com/salesforcecli/plugin-source/commit/f1b0c64a3ec75bba48e0a552e53a78af5a4d9251)) ## [2.3.14](https://github.com/salesforcecli/plugin-source/compare/2.3.13...2.3.14) (2023-01-14) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 7.5.22 to 7.7.0 ([#696](https://github.com/salesforcecli/plugin-source/issues/696)) ([998425c](https://github.com/salesforcecli/plugin-source/commit/998425c8ea3cfcfc0b91b7b6c217948bcc75336a)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 7.5.22 to 7.7.0 ([#696](https://github.com/salesforcecli/plugin-source/issues/696)) ([998425c](https://github.com/salesforcecli/plugin-source/commit/998425c8ea3cfcfc0b91b7b6c217948bcc75336a)) ## [2.3.13](https://github.com/salesforcecli/plugin-source/compare/2.3.12...2.3.13) (2023-01-14) - ### Bug Fixes -* **deps:** bump @salesforce/apex-node from 1.4.0 to 1.6.0 ([#695](https://github.com/salesforcecli/plugin-source/issues/695)) ([bcc0cd1](https://github.com/salesforcecli/plugin-source/commit/bcc0cd192ee27c23bbbca6f044927b435474d75a)) - - +- **deps:** bump @salesforce/apex-node from 1.4.0 to 1.6.0 ([#695](https://github.com/salesforcecli/plugin-source/issues/695)) ([bcc0cd1](https://github.com/salesforcecli/plugin-source/commit/bcc0cd192ee27c23bbbca6f044927b435474d75a)) ## [2.3.12](https://github.com/salesforcecli/plugin-source/compare/2.3.11...2.3.12) (2023-01-05) - ### Bug Fixes -* **deps:** bump json5 from 1.0.1 to 1.0.2 ([#688](https://github.com/salesforcecli/plugin-source/issues/688)) ([d6ae9f5](https://github.com/salesforcecli/plugin-source/commit/d6ae9f5594b19fe8b6f23e8d7c3e0d801b06ff48)) - - +- **deps:** bump json5 from 1.0.1 to 1.0.2 ([#688](https://github.com/salesforcecli/plugin-source/issues/688)) ([d6ae9f5](https://github.com/salesforcecli/plugin-source/commit/d6ae9f5594b19fe8b6f23e8d7c3e0d801b06ff48)) ## [2.3.11](https://github.com/salesforcecli/plugin-source/compare/2.3.10...2.3.11) (2022-12-31) - ### Bug Fixes -* **deps:** bump @oclif/core from 1.22.0 to 1.23.0 ([#684](https://github.com/salesforcecli/plugin-source/issues/684)) ([f27da0f](https://github.com/salesforcecli/plugin-source/commit/f27da0f5d61fa6b766840a40ebe0b747e1d14f1a)) - - +- **deps:** bump @oclif/core from 1.22.0 to 1.23.0 ([#684](https://github.com/salesforcecli/plugin-source/issues/684)) ([f27da0f](https://github.com/salesforcecli/plugin-source/commit/f27da0f5d61fa6b766840a40ebe0b747e1d14f1a)) ## [2.3.10](https://github.com/salesforcecli/plugin-source/compare/2.3.9...2.3.10) (2022-12-31) - ### Bug Fixes -* **deps:** bump @salesforce/command from 5.2.33 to 5.2.35 ([#686](https://github.com/salesforcecli/plugin-source/issues/686)) ([a994c59](https://github.com/salesforcecli/plugin-source/commit/a994c595162e10b8f8d570d64bdd72d9e14d24f9)) - - +- **deps:** bump @salesforce/command from 5.2.33 to 5.2.35 ([#686](https://github.com/salesforcecli/plugin-source/issues/686)) ([a994c59](https://github.com/salesforcecli/plugin-source/commit/a994c595162e10b8f8d570d64bdd72d9e14d24f9)) ## [2.3.9](https://github.com/salesforcecli/plugin-source/compare/2.3.8...2.3.9) (2022-12-17) - ### Bug Fixes -* **deps:** bump @oclif/core from 1.20.4 to 1.22.0 ([#676](https://github.com/salesforcecli/plugin-source/issues/676)) ([f82266f](https://github.com/salesforcecli/plugin-source/commit/f82266f4e805f55912bd8a75717109fa878ee39e)) - - +- **deps:** bump @oclif/core from 1.20.4 to 1.22.0 ([#676](https://github.com/salesforcecli/plugin-source/issues/676)) ([f82266f](https://github.com/salesforcecli/plugin-source/commit/f82266f4e805f55912bd8a75717109fa878ee39e)) ## [2.3.8](https://github.com/salesforcecli/plugin-source/compare/2.3.7...2.3.8) (2022-12-16) - - ## [2.3.7](https://github.com/salesforcecli/plugin-source/compare/2.3.6...2.3.7) (2022-12-01) - ### Bug Fixes -* **deps:** bump @salesforce/core from 3.32.4 to 3.32.5 ([#660](https://github.com/salesforcecli/plugin-source/issues/660)) ([b83a2ed](https://github.com/salesforcecli/plugin-source/commit/b83a2edc39f216a0eec9b42b028b1f42f07ea48a)) - - +- **deps:** bump @salesforce/core from 3.32.4 to 3.32.5 ([#660](https://github.com/salesforcecli/plugin-source/issues/660)) ([b83a2ed](https://github.com/salesforcecli/plugin-source/commit/b83a2edc39f216a0eec9b42b028b1f42f07ea48a)) ## [2.3.6](https://github.com/salesforcecli/plugin-source/compare/2.3.5...2.3.6) (2022-12-01) - ### Bug Fixes -* guard against undefined file path in results ([#659](https://github.com/salesforcecli/plugin-source/issues/659)) ([0262ea0](https://github.com/salesforcecli/plugin-source/commit/0262ea043c2aa141ffe194d9d45eeaab93e394a9)) - - +- guard against undefined file path in results ([#659](https://github.com/salesforcecli/plugin-source/issues/659)) ([0262ea0](https://github.com/salesforcecli/plugin-source/commit/0262ea043c2aa141ffe194d9d45eeaab93e394a9)) ## [2.3.5](https://github.com/salesforcecli/plugin-source/compare/2.3.4...2.3.5) (2022-11-18) - ### Bug Fixes -* bump SDR and regen lock file ([#650](https://github.com/salesforcecli/plugin-source/issues/650)) ([db9ecb4](https://github.com/salesforcecli/plugin-source/commit/db9ecb432e13c13e7c655c30bc1e5aa69c291237)) - - +- bump SDR and regen lock file ([#650](https://github.com/salesforcecli/plugin-source/issues/650)) ([db9ecb4](https://github.com/salesforcecli/plugin-source/commit/db9ecb432e13c13e7c655c30bc1e5aa69c291237)) ## [2.3.4](https://github.com/salesforcecli/plugin-source/compare/2.3.3...2.3.4) (2022-11-12) - ### Bug Fixes -* bump sdr and core for fixes ([63f8b0c](https://github.com/salesforcecli/plugin-source/commit/63f8b0c371e849dd414b47c9515f9a517f786bf4)) - - +- bump sdr and core for fixes ([63f8b0c](https://github.com/salesforcecli/plugin-source/commit/63f8b0c371e849dd414b47c9515f9a517f786bf4)) ## [2.3.3](https://github.com/salesforcecli/plugin-source/compare/2.3.2...2.3.3) (2022-11-12) - ### Bug Fixes -* bump sdr and core for fixes ([5a91d6e](https://github.com/salesforcecli/plugin-source/commit/5a91d6e0b2277348139b239b956dbc4fdb92bde2)) - - +- bump sdr and core for fixes ([5a91d6e](https://github.com/salesforcecli/plugin-source/commit/5a91d6e0b2277348139b239b956dbc4fdb92bde2)) ## [2.3.2](https://github.com/salesforcecli/plugin-source/compare/2.3.1...2.3.2) (2022-11-09) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 7.5.0 to 7.5.2 ([#641](https://github.com/salesforcecli/plugin-source/issues/641)) ([4220b78](https://github.com/salesforcecli/plugin-source/commit/4220b786f1ea1f62ac112a4389fec816844ebe41)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 7.5.0 to 7.5.2 ([#641](https://github.com/salesforcecli/plugin-source/issues/641)) ([4220b78](https://github.com/salesforcecli/plugin-source/commit/4220b786f1ea1f62ac112a4389fec816844ebe41)) ## [2.3.1](https://github.com/salesforcecli/plugin-source/compare/2.3.0...2.3.1) (2022-11-05) - ### Bug Fixes -* **deps:** bump tslib from 2.4.0 to 2.4.1 ([#638](https://github.com/salesforcecli/plugin-source/issues/638)) ([f9424f4](https://github.com/salesforcecli/plugin-source/commit/f9424f490b5d0d10e3d8780ac4cedcdd0229f77a)) - - +- **deps:** bump tslib from 2.4.0 to 2.4.1 ([#638](https://github.com/salesforcecli/plugin-source/issues/638)) ([f9424f4](https://github.com/salesforcecli/plugin-source/commit/f9424f490b5d0d10e3d8780ac4cedcdd0229f77a)) # [2.3.0](https://github.com/salesforcecli/plugin-source/compare/2.2.0...2.3.0) (2022-11-01) - ### Features -* display replacements on push/deploy ([#628](https://github.com/salesforcecli/plugin-source/issues/628)) ([6fd2045](https://github.com/salesforcecli/plugin-source/commit/6fd20457dc3885d91fdfffba66a1077b100f1de0)) - - +- display replacements on push/deploy ([#628](https://github.com/salesforcecli/plugin-source/issues/628)) ([6fd2045](https://github.com/salesforcecli/plugin-source/commit/6fd20457dc3885d91fdfffba66a1077b100f1de0)) # [2.2.0](https://github.com/salesforcecli/plugin-source/compare/2.1.3...2.2.0) (2022-11-01) - ### Features -* add retrievetargetdir to source:retrieve ([#624](https://github.com/salesforcecli/plugin-source/issues/624)) ([7c0a013](https://github.com/salesforcecli/plugin-source/commit/7c0a0130e563652fdc11dabf65a00c77c88db5d6)) - - +- add retrievetargetdir to source:retrieve ([#624](https://github.com/salesforcecli/plugin-source/issues/624)) ([7c0a013](https://github.com/salesforcecli/plugin-source/commit/7c0a0130e563652fdc11dabf65a00c77c88db5d6)) ## [2.1.3](https://github.com/salesforcecli/plugin-source/compare/2.1.2...2.1.3) (2022-10-31) - ### Bug Fixes -* add hook and doctor diagnostic tests ([#629](https://github.com/salesforcecli/plugin-source/issues/629)) ([f41cb57](https://github.com/salesforcecli/plugin-source/commit/f41cb57c186226d03e55947f15f7820549dcb10e)) - - +- add hook and doctor diagnostic tests ([#629](https://github.com/salesforcecli/plugin-source/issues/629)) ([f41cb57](https://github.com/salesforcecli/plugin-source/commit/f41cb57c186226d03e55947f15f7820549dcb10e)) ## [2.1.2](https://github.com/salesforcecli/plugin-source/compare/2.1.1...2.1.2) (2022-10-29) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 7.0.1 to 7.4.0 ([#633](https://github.com/salesforcecli/plugin-source/issues/633)) ([8d7ae01](https://github.com/salesforcecli/plugin-source/commit/8d7ae01d2b8d3d8d8180388d83ccc45a6ab77bfd)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 7.0.1 to 7.4.0 ([#633](https://github.com/salesforcecli/plugin-source/issues/633)) ([8d7ae01](https://github.com/salesforcecli/plugin-source/commit/8d7ae01d2b8d3d8d8180388d83ccc45a6ab77bfd)) ## [2.1.1](https://github.com/salesforcecli/plugin-source/compare/2.1.0...2.1.1) (2022-10-29) - ### Bug Fixes -* **deps:** bump @salesforce/kit from 1.7.0 to 1.7.1 ([#635](https://github.com/salesforcecli/plugin-source/issues/635)) ([37cb1fa](https://github.com/salesforcecli/plugin-source/commit/37cb1fab6535dba3d274ba1bde337f1ea010dd3d)) - - +- **deps:** bump @salesforce/kit from 1.7.0 to 1.7.1 ([#635](https://github.com/salesforcecli/plugin-source/issues/635)) ([37cb1fa](https://github.com/salesforcecli/plugin-source/commit/37cb1fab6535dba3d274ba1bde337f1ea010dd3d)) # [2.1.0](https://github.com/salesforcecli/plugin-source/compare/2.0.26...2.1.0) (2022-10-28) - ### Features -* use swc in bin/dev ([66debb4](https://github.com/salesforcecli/plugin-source/commit/66debb4a4fc2743c8f51510065381d95eb454756)) - - +- use swc in bin/dev ([66debb4](https://github.com/salesforcecli/plugin-source/commit/66debb4a4fc2743c8f51510065381d95eb454756)) ## [2.0.26](https://github.com/salesforcecli/plugin-source/compare/2.0.25...2.0.26) (2022-10-22) - ### Bug Fixes -* **deps:** bump @salesforce/command from 5.2.8 to 5.2.13 ([#620](https://github.com/salesforcecli/plugin-source/issues/620)) ([8c6d514](https://github.com/salesforcecli/plugin-source/commit/8c6d514cc0d561f485fd6148899e22baa8ea95ae)) - - +- **deps:** bump @salesforce/command from 5.2.8 to 5.2.13 ([#620](https://github.com/salesforcecli/plugin-source/issues/620)) ([8c6d514](https://github.com/salesforcecli/plugin-source/commit/8c6d514cc0d561f485fd6148899e22baa8ea95ae)) ## [2.0.25](https://github.com/salesforcecli/plugin-source/compare/2.0.24...2.0.25) (2022-10-18) - ### Bug Fixes -* **deps:** major bump sdr ([c243af7](https://github.com/salesforcecli/plugin-source/commit/c243af746fe872030eb32ad6f3942f847d6f6944)) - - +- **deps:** major bump sdr ([c243af7](https://github.com/salesforcecli/plugin-source/commit/c243af746fe872030eb32ad6f3942f847d6f6944)) ## [2.0.24](https://github.com/salesforcecli/plugin-source/compare/2.0.23...2.0.24) (2022-10-17) - ### Bug Fixes -* display error message from response ([#608](https://github.com/salesforcecli/plugin-source/issues/608)) ([6ba254e](https://github.com/salesforcecli/plugin-source/commit/6ba254e731e48d4b8787fad7d231c075401c4eaf)) - - +- display error message from response ([#608](https://github.com/salesforcecli/plugin-source/issues/608)) ([6ba254e](https://github.com/salesforcecli/plugin-source/commit/6ba254e731e48d4b8787fad7d231c075401c4eaf)) ## [2.0.23](https://github.com/salesforcecli/plugin-source/compare/2.0.22...2.0.23) (2022-10-16) - ### Bug Fixes -* **deps:** bump @salesforce/source-tracking from 2.2.8 to 2.2.9 ([#613](https://github.com/salesforcecli/plugin-source/issues/613)) ([77e2504](https://github.com/salesforcecli/plugin-source/commit/77e25044ae450a04a41da5dec89fbec6a8cc4495)) - - +- **deps:** bump @salesforce/source-tracking from 2.2.8 to 2.2.9 ([#613](https://github.com/salesforcecli/plugin-source/issues/613)) ([77e2504](https://github.com/salesforcecli/plugin-source/commit/77e25044ae450a04a41da5dec89fbec6a8cc4495)) ## [2.0.22](https://github.com/salesforcecli/plugin-source/compare/2.0.21...2.0.22) (2022-10-16) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 6.8.6 to 6.9.1 ([#614](https://github.com/salesforcecli/plugin-source/issues/614)) ([ea639b5](https://github.com/salesforcecli/plugin-source/commit/ea639b512d991c249dc7082f5afb3a5481abbce9)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 6.8.6 to 6.9.1 ([#614](https://github.com/salesforcecli/plugin-source/issues/614)) ([ea639b5](https://github.com/salesforcecli/plugin-source/commit/ea639b512d991c249dc7082f5afb3a5481abbce9)) ## [2.0.21](https://github.com/salesforcecli/plugin-source/compare/2.0.20...2.0.21) (2022-10-15) - ### Bug Fixes -* **deps:** bump vm2 from 3.9.9 to 3.9.11 ([#591](https://github.com/salesforcecli/plugin-source/issues/591)) ([4e5d67b](https://github.com/salesforcecli/plugin-source/commit/4e5d67bd507f0c20199aa0519fc3723a165c7928)) - - +- **deps:** bump vm2 from 3.9.9 to 3.9.11 ([#591](https://github.com/salesforcecli/plugin-source/issues/591)) ([4e5d67b](https://github.com/salesforcecli/plugin-source/commit/4e5d67bd507f0c20199aa0519fc3723a165c7928)) ## [2.0.20](https://github.com/salesforcecli/plugin-source/compare/2.0.19...2.0.20) (2022-10-15) - ### Bug Fixes -* **deps:** bump @oclif/core from 1.16.3 to 1.18.0 ([#612](https://github.com/salesforcecli/plugin-source/issues/612)) ([f3b69ac](https://github.com/salesforcecli/plugin-source/commit/f3b69ac0e24b6a7d7fd6a388da9dc2909ee2e73b)) - - +- **deps:** bump @oclif/core from 1.16.3 to 1.18.0 ([#612](https://github.com/salesforcecli/plugin-source/issues/612)) ([f3b69ac](https://github.com/salesforcecli/plugin-source/commit/f3b69ac0e24b6a7d7fd6a388da9dc2909ee2e73b)) ## [2.0.19](https://github.com/salesforcecli/plugin-source/compare/2.0.18...2.0.19) (2022-10-13) - ### Bug Fixes -* bump apex-node ([#604](https://github.com/salesforcecli/plugin-source/issues/604)) ([e71b0d5](https://github.com/salesforcecli/plugin-source/commit/e71b0d5fb8beb9af04473b6ce65194b48646784e)) - - +- bump apex-node ([#604](https://github.com/salesforcecli/plugin-source/issues/604)) ([e71b0d5](https://github.com/salesforcecli/plugin-source/commit/e71b0d5fb8beb9af04473b6ce65194b48646784e)) ## [2.0.18](https://github.com/salesforcecli/plugin-source/compare/2.0.17...2.0.18) (2022-10-07) - ### Bug Fixes -* **deps:** bump jsforce from 2.0.0-beta.18 to 2.0.0-beta.19 ([#601](https://github.com/salesforcecli/plugin-source/issues/601)) ([33a3a39](https://github.com/salesforcecli/plugin-source/commit/33a3a39873695d2106abcbef61737dbf6970bac0)) - - +- **deps:** bump jsforce from 2.0.0-beta.18 to 2.0.0-beta.19 ([#601](https://github.com/salesforcecli/plugin-source/issues/601)) ([33a3a39](https://github.com/salesforcecli/plugin-source/commit/33a3a39873695d2106abcbef61737dbf6970bac0)) ## [2.0.17](https://github.com/salesforcecli/plugin-source/compare/2.0.16...2.0.17) (2022-10-06) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 6.8.5 to 6.8.6 ([#599](https://github.com/salesforcecli/plugin-source/issues/599)) ([c940e5b](https://github.com/salesforcecli/plugin-source/commit/c940e5b908fce259930dbb914c09ecbac89d5e5e)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 6.8.5 to 6.8.6 ([#599](https://github.com/salesforcecli/plugin-source/issues/599)) ([c940e5b](https://github.com/salesforcecli/plugin-source/commit/c940e5b908fce259930dbb914c09ecbac89d5e5e)) ## [2.0.16](https://github.com/salesforcecli/plugin-source/compare/2.0.15...2.0.16) (2022-09-23) - ### Bug Fixes -* **deps:** bump @salesforce/source-tracking from 2.2.1 to 2.2.3 ([#584](https://github.com/salesforcecli/plugin-source/issues/584)) ([b1e6f72](https://github.com/salesforcecli/plugin-source/commit/b1e6f724bf4c5458ea3466db9173d51a1e496915)) - - +- **deps:** bump @salesforce/source-tracking from 2.2.1 to 2.2.3 ([#584](https://github.com/salesforcecli/plugin-source/issues/584)) ([b1e6f72](https://github.com/salesforcecli/plugin-source/commit/b1e6f724bf4c5458ea3466db9173d51a1e496915)) ## [2.0.15](https://github.com/salesforcecli/plugin-source/compare/2.0.14...2.0.15) (2022-09-21) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 6.8.0 to 6.8.1 ([#580](https://github.com/salesforcecli/plugin-source/issues/580)) ([a2a792c](https://github.com/salesforcecli/plugin-source/commit/a2a792ce013c6851d9eaeec163256b7cfca8741c)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 6.8.0 to 6.8.1 ([#580](https://github.com/salesforcecli/plugin-source/issues/580)) ([a2a792c](https://github.com/salesforcecli/plugin-source/commit/a2a792ce013c6851d9eaeec163256b7cfca8741c)) ## [2.0.14](https://github.com/salesforcecli/plugin-source/compare/v2.0.13...2.0.14) (2022-09-21) - ### Bug Fixes -* **deps:** bump @salesforce/source-deploy-retrieve from 6.2.6 to 6.8.0 ([#576](https://github.com/salesforcecli/plugin-source/issues/576)) ([42c2654](https://github.com/salesforcecli/plugin-source/commit/42c2654ce9ddb2dbc3c82d1fecbc7aaa91791ae6)) - - +- **deps:** bump @salesforce/source-deploy-retrieve from 6.2.6 to 6.8.0 ([#576](https://github.com/salesforcecli/plugin-source/issues/576)) ([42c2654](https://github.com/salesforcecli/plugin-source/commit/42c2654ce9ddb2dbc3c82d1fecbc7aaa91791ae6)) ## [2.0.13](https://github.com/salesforcecli/plugin-source/compare/v2.0.12...v2.0.13) (2022-08-20) - - ## [2.0.12](https://github.com/salesforcecli/plugin-source/compare/v2.0.11...v2.0.12) (2022-08-15) - ### Bug Fixes -* exclude sourcepath from component set builder ([#553](https://github.com/salesforcecli/plugin-source/issues/553)) ([b678d0c](https://github.com/salesforcecli/plugin-source/commit/b678d0c9023fc6a0f5c816b40d22ab4803356834)) - - +- exclude sourcepath from component set builder ([#553](https://github.com/salesforcecli/plugin-source/issues/553)) ([b678d0c](https://github.com/salesforcecli/plugin-source/commit/b678d0c9023fc6a0f5c816b40d22ab4803356834)) ## [2.0.11](https://github.com/salesforcecli/plugin-source/compare/v2.0.10...v2.0.11) (2022-07-26) - ### Bug Fixes -* bump SDR ([#541](https://github.com/salesforcecli/plugin-source/issues/541)) ([dcb10ab](https://github.com/salesforcecli/plugin-source/commit/dcb10ab8daa414fecf9d8d3115ebd8ab8aebcdd7)) - - +- bump SDR ([#541](https://github.com/salesforcecli/plugin-source/issues/541)) ([dcb10ab](https://github.com/salesforcecli/plugin-source/commit/dcb10ab8daa414fecf9d8d3115ebd8ab8aebcdd7)) ## [2.0.10](https://github.com/salesforcecli/plugin-source/compare/v2.0.9...v2.0.10) (2022-07-25) - ### Bug Fixes -* caret for jsforce ([#540](https://github.com/salesforcecli/plugin-source/issues/540)) ([2142e70](https://github.com/salesforcecli/plugin-source/commit/2142e701b503d84bb38b6557283c3a49b1ee0b92)) - - +- caret for jsforce ([#540](https://github.com/salesforcecli/plugin-source/issues/540)) ([2142e70](https://github.com/salesforcecli/plugin-source/commit/2142e701b503d84bb38b6557283c3a49b1ee0b92)) ## [2.0.9](https://github.com/salesforcecli/plugin-source/compare/v2.0.8...v2.0.9) (2022-07-20) - ### Bug Fixes -* fixes exclusive flags for mdapi/source:deploy when using quickdeploy ([#521](https://github.com/salesforcecli/plugin-source/issues/521)) ([7c52a05](https://github.com/salesforcecli/plugin-source/commit/7c52a05c91484dd1135b6b7498c4e89718092256)) - - +- fixes exclusive flags for mdapi/source:deploy when using quickdeploy ([#521](https://github.com/salesforcecli/plugin-source/issues/521)) ([7c52a05](https://github.com/salesforcecli/plugin-source/commit/7c52a05c91484dd1135b6b7498c4e89718092256)) ## [2.0.8](https://github.com/salesforcecli/plugin-source/compare/v2.0.7...v2.0.8) (2022-07-18) - ### Bug Fixes -* try/finally on pollStatus to handle throws from timeout ([#538](https://github.com/salesforcecli/plugin-source/issues/538)) ([68ff738](https://github.com/salesforcecli/plugin-source/commit/68ff73850f853d5951be8667a8fc807ecf78f91f)) - - +- try/finally on pollStatus to handle throws from timeout ([#538](https://github.com/salesforcecli/plugin-source/issues/538)) ([68ff738](https://github.com/salesforcecli/plugin-source/commit/68ff73850f853d5951be8667a8fc807ecf78f91f)) ## [2.0.7](https://github.com/salesforcecli/plugin-source/compare/v2.0.6...v2.0.7) (2022-07-07) - ### Bug Fixes -* bump SDR ([#537](https://github.com/salesforcecli/plugin-source/issues/537)) ([fa405e4](https://github.com/salesforcecli/plugin-source/commit/fa405e4e9cdaee40d75b1c05cebb449a68533f30)) - - +- bump SDR ([#537](https://github.com/salesforcecli/plugin-source/issues/537)) ([fa405e4](https://github.com/salesforcecli/plugin-source/commit/fa405e4e9cdaee40d75b1c05cebb449a68533f30)) ## [2.0.6](https://github.com/salesforcecli/plugin-source/compare/v2.0.5...v2.0.6) (2022-07-07) - ### Bug Fixes -* isRestDeploy correctly handles org-metadata-rest-deploy config conversion ([#535](https://github.com/salesforcecli/plugin-source/issues/535)) ([dd7e776](https://github.com/salesforcecli/plugin-source/commit/dd7e7763ade1244fdc66a34892a52d0a779f9b58)) - - +- isRestDeploy correctly handles org-metadata-rest-deploy config conversion ([#535](https://github.com/salesforcecli/plugin-source/issues/535)) ([dd7e776](https://github.com/salesforcecli/plugin-source/commit/dd7e7763ade1244fdc66a34892a52d0a779f9b58)) ## [2.0.5](https://github.com/salesforcecli/plugin-source/compare/v2.0.4...v2.0.5) (2022-07-06) - ### Bug Fixes -* apex-node from parking-orbit ([#533](https://github.com/salesforcecli/plugin-source/issues/533)) ([ebaf5ed](https://github.com/salesforcecli/plugin-source/commit/ebaf5edef0ec15ba2c2e2cf541701e7db08f10bf)) - - +- apex-node from parking-orbit ([#533](https://github.com/salesforcecli/plugin-source/issues/533)) ([ebaf5ed](https://github.com/salesforcecli/plugin-source/commit/ebaf5edef0ec15ba2c2e2cf541701e7db08f10bf)) ## [2.0.4](https://github.com/salesforcecli/plugin-source/compare/v2.0.3...v2.0.4) (2022-07-05) - ### Bug Fixes -* ebikes nuts fix ([#522](https://github.com/salesforcecli/plugin-source/issues/522)) ([990a2e1](https://github.com/salesforcecli/plugin-source/commit/990a2e1e6ba34fbf0c855358a433a3503faf708d)) - - +- ebikes nuts fix ([#522](https://github.com/salesforcecli/plugin-source/issues/522)) ([990a2e1](https://github.com/salesforcecli/plugin-source/commit/990a2e1e6ba34fbf0c855358a433a3503faf708d)) ## [2.0.3](https://github.com/salesforcecli/plugin-source/compare/v2.0.2...v2.0.3) (2022-06-23) - - ## [2.0.2](https://github.com/salesforcecli/plugin-source/compare/v2.0.1...v2.0.2) (2022-06-23) - - ## [2.0.1](https://github.com/salesforcecli/plugin-source/compare/v2.0.0...v2.0.1) (2022-06-16) - ### Bug Fixes -* let server determine testlevel when deploying to a prod org by passing `undefined` ([#509](https://github.com/salesforcecli/plugin-source/issues/509)) ([6d5a995](https://github.com/salesforcecli/plugin-source/commit/6d5a99515939eb9a356bd039d872e4ffad8158b7)) - - +- let server determine testlevel when deploying to a prod org by passing `undefined` ([#509](https://github.com/salesforcecli/plugin-source/issues/509)) ([6d5a995](https://github.com/salesforcecli/plugin-source/commit/6d5a99515939eb9a356bd039d872e4ffad8158b7)) # [2.0.0](https://github.com/salesforcecli/plugin-source/compare/v1.10.2...v2.0.0) (2022-06-15) - - ## [1.10.2](https://github.com/salesforcecli/plugin-source/compare/v1.10.1...v1.10.2) (2022-05-31) - ### Bug Fixes -* default min line number to 1 when 100 pct coverage ([#494](https://github.com/salesforcecli/plugin-source/issues/494)) ([c974010](https://github.com/salesforcecli/plugin-source/commit/c974010b9e6ec54e9b4092e9918cdf4e5cbc5b46)) - - +- default min line number to 1 when 100 pct coverage ([#494](https://github.com/salesforcecli/plugin-source/issues/494)) ([c974010](https://github.com/salesforcecli/plugin-source/commit/c974010b9e6ec54e9b4092e9918cdf4e5cbc5b46)) ## [1.10.1](https://github.com/salesforcecli/plugin-source/compare/v1.10.0...v1.10.1) (2022-05-27) - ### Bug Fixes -* import coverageUtils from parent folder ([#493](https://github.com/salesforcecli/plugin-source/issues/493)) ([c4f471e](https://github.com/salesforcecli/plugin-source/commit/c4f471e97b50a43c1809518432f7ec4dddc05041)) - - +- import coverageUtils from parent folder ([#493](https://github.com/salesforcecli/plugin-source/issues/493)) ([c4f471e](https://github.com/salesforcecli/plugin-source/commit/c4f471e97b50a43c1809518432f7ec4dddc05041)) # [1.10.0](https://github.com/salesforcecli/plugin-source/compare/v1.9.9...v1.10.0) (2022-05-26) - ### Features -* add code coverage and junit reporting ([#491](https://github.com/salesforcecli/plugin-source/issues/491)) ([3e6ff90](https://github.com/salesforcecli/plugin-source/commit/3e6ff908d937c526abe219831f67e749a828c640)) - - +- add code coverage and junit reporting ([#491](https://github.com/salesforcecli/plugin-source/issues/491)) ([3e6ff90](https://github.com/salesforcecli/plugin-source/commit/3e6ff908d937c526abe219831f67e749a828c640)) ## [1.9.9](https://github.com/salesforcecli/plugin-source/compare/v1.9.8...v1.9.9) (2022-05-18) - - ## [1.9.8](https://github.com/salesforcecli/plugin-source/compare/v1.9.7...v1.9.8) (2022-05-17) - ### Bug Fixes -* mdapi deploy negative one ([#487](https://github.com/salesforcecli/plugin-source/issues/487)) ([c7e2494](https://github.com/salesforcecli/plugin-source/commit/c7e24941f770336ea31e067067c12942ec01bf49)) - - +- mdapi deploy negative one ([#487](https://github.com/salesforcecli/plugin-source/issues/487)) ([c7e2494](https://github.com/salesforcecli/plugin-source/commit/c7e24941f770336ea31e067067c12942ec01bf49)) ## [1.9.7](https://github.com/salesforcecli/plugin-source/compare/v1.9.6...v1.9.7) (2022-05-04) - - ## [1.9.6](https://github.com/salesforcecli/plugin-source/compare/v1.9.5...v1.9.6) (2022-04-29) - ### Bug Fixes -* use fixed stl, bump other deps for maintenance ([#477](https://github.com/salesforcecli/plugin-source/issues/477)) ([7c7f411](https://github.com/salesforcecli/plugin-source/commit/7c7f411d6f9e55141ac077cafc1e0f1e1efe5120)) - - +- use fixed stl, bump other deps for maintenance ([#477](https://github.com/salesforcecli/plugin-source/issues/477)) ([7c7f411](https://github.com/salesforcecli/plugin-source/commit/7c7f411d6f9e55141ac077cafc1e0f1e1efe5120)) ## [1.9.5](https://github.com/salesforcecli/plugin-source/compare/v1.9.4...v1.9.5) (2022-04-28) - ### Bug Fixes -* pull non-default directory in default project ([#471](https://github.com/salesforcecli/plugin-source/issues/471)) ([02d91ca](https://github.com/salesforcecli/plugin-source/commit/02d91caf1e39c00a32d53012f6916a86dea2b2f8)) - - +- pull non-default directory in default project ([#471](https://github.com/salesforcecli/plugin-source/issues/471)) ([02d91ca](https://github.com/salesforcecli/plugin-source/commit/02d91caf1e39c00a32d53012f6916a86dea2b2f8)) ## [1.9.4](https://github.com/salesforcecli/plugin-source/compare/v1.9.3...v1.9.4) (2022-04-26) - ### Reverts -* Revert "test: nuts for nested LWC" ([13cd75b](https://github.com/salesforcecli/plugin-source/commit/13cd75b47608af55be5e45842bc14edb866c93ec)) - - +- Revert "test: nuts for nested LWC" ([13cd75b](https://github.com/salesforcecli/plugin-source/commit/13cd75b47608af55be5e45842bc14edb866c93ec)) ## [1.9.3](https://github.com/salesforcecli/plugin-source/compare/v1.9.2...v1.9.3) (2022-04-07) - ### Bug Fixes -* bump to latest sdr ([#467](https://github.com/salesforcecli/plugin-source/issues/467)) ([a71881c](https://github.com/salesforcecli/plugin-source/commit/a71881c276f160b0c50cd4d7bee2bad2096eef1e)) - - +- bump to latest sdr ([#467](https://github.com/salesforcecli/plugin-source/issues/467)) ([a71881c](https://github.com/salesforcecli/plugin-source/commit/a71881c276f160b0c50cd4d7bee2bad2096eef1e)) ## [1.9.2](https://github.com/salesforcecli/plugin-source/compare/v1.9.1...v1.9.2) (2022-03-25) - ### Bug Fixes -* fix from stl ([#460](https://github.com/salesforcecli/plugin-source/issues/460)) ([1ac35ac](https://github.com/salesforcecli/plugin-source/commit/1ac35aca178c21fdae9100064fafaccf3d66cf02)) - - +- fix from stl ([#460](https://github.com/salesforcecli/plugin-source/issues/460)) ([1ac35ac](https://github.com/salesforcecli/plugin-source/commit/1ac35aca178c21fdae9100064fafaccf3d66cf02)) ## [1.9.1](https://github.com/salesforcecli/plugin-source/compare/v1.9.0...v1.9.1) (2022-03-25) - ### Bug Fixes -* bump stl for graceful ([#459](https://github.com/salesforcecli/plugin-source/issues/459)) ([b611415](https://github.com/salesforcecli/plugin-source/commit/b611415d32f29ac5f8bc091652031d635d7338fe)) - - +- bump stl for graceful ([#459](https://github.com/salesforcecli/plugin-source/issues/459)) ([b611415](https://github.com/salesforcecli/plugin-source/commit/b611415d32f29ac5f8bc091652031d635d7338fe)) # [1.9.0](https://github.com/salesforcecli/plugin-source/compare/v1.8.20...v1.9.0) (2022-03-23) - ### Features -* GA new tracking commands ([#457](https://github.com/salesforcecli/plugin-source/issues/457)) ([eb54c09](https://github.com/salesforcecli/plugin-source/commit/eb54c097d0a714c3c42f0a435941d2f30d609eea)) - - +- GA new tracking commands ([#457](https://github.com/salesforcecli/plugin-source/issues/457)) ([eb54c09](https://github.com/salesforcecli/plugin-source/commit/eb54c097d0a714c3c42f0a435941d2f30d609eea)) ## [1.8.20](https://github.com/salesforcecli/plugin-source/compare/v1.8.19...v1.8.20) (2022-03-17) - ### Bug Fixes -* error structure for json on push/pull ([5f36a37](https://github.com/salesforcecli/plugin-source/commit/5f36a3720c08cd909e567249b597fdbae2e35dd1)) - - +- error structure for json on push/pull ([5f36a37](https://github.com/salesforcecli/plugin-source/commit/5f36a3720c08cd909e567249b597fdbae2e35dd1)) ## [1.8.19](https://github.com/salesforcecli/plugin-source/compare/v1.8.18...v1.8.19) (2022-03-16) - ### Bug Fixes -* move command force to plugin-source ([#451](https://github.com/salesforcecli/plugin-source/issues/451)) ([5da7884](https://github.com/salesforcecli/plugin-source/commit/5da7884953c068bcf37f3434193cae309fef8573)) - - +- move command force to plugin-source ([#451](https://github.com/salesforcecli/plugin-source/issues/451)) ([5da7884](https://github.com/salesforcecli/plugin-source/commit/5da7884953c068bcf37f3434193cae309fef8573)) ## [1.8.18](https://github.com/salesforcecli/plugin-source/compare/v1.8.17...v1.8.18) (2022-03-07) - ### Bug Fixes -* revert beta GA ([#446](https://github.com/salesforcecli/plugin-source/issues/446)) ([0efcaa1](https://github.com/salesforcecli/plugin-source/commit/0efcaa11c7c3d3eaed9787486c52295adc5aa4b7)) - - +- revert beta GA ([#446](https://github.com/salesforcecli/plugin-source/issues/446)) ([0efcaa1](https://github.com/salesforcecli/plugin-source/commit/0efcaa11c7c3d3eaed9787486c52295adc5aa4b7)) ## [1.8.17](https://github.com/salesforcecli/plugin-source/compare/v1.8.16...v1.8.17) (2022-03-01) - ### Bug Fixes -* use CSB from SDR ([#430](https://github.com/salesforcecli/plugin-source/issues/430)) ([80e4bdd](https://github.com/salesforcecli/plugin-source/commit/80e4bdd313b55f4b9d37a7a792885d7503e1fbfc)) - - +- use CSB from SDR ([#430](https://github.com/salesforcecli/plugin-source/issues/430)) ([80e4bdd](https://github.com/salesforcecli/plugin-source/commit/80e4bdd313b55f4b9d37a7a792885d7503e1fbfc)) ## [1.8.16](https://github.com/salesforcecli/plugin-source/compare/v1.8.15...v1.8.16) (2022-02-27) - ### Bug Fixes -* run mdapi NUTs in CI ([#431](https://github.com/salesforcecli/plugin-source/issues/431)) ([e33fd1e](https://github.com/salesforcecli/plugin-source/commit/e33fd1e93a92cd95586d29d8fb0ff6cb6e038fbb)) - - +- run mdapi NUTs in CI ([#431](https://github.com/salesforcecli/plugin-source/issues/431)) ([e33fd1e](https://github.com/salesforcecli/plugin-source/commit/e33fd1e93a92cd95586d29d8fb0ff6cb6e038fbb)) ## [1.8.15](https://github.com/salesforcecli/plugin-source/compare/v1.8.14...v1.8.15) (2022-02-24) - - ## [1.8.14](https://github.com/salesforcecli/plugin-source/compare/v1.8.13...v1.8.14) (2022-02-23) - - ## [1.8.13](https://github.com/salesforcecli/plugin-source/compare/v1.8.12...v1.8.13) (2022-02-23) - - ## [1.8.12](https://github.com/salesforcecli/plugin-source/compare/v1.8.11...v1.8.12) (2022-02-14) - - ## [1.8.11](https://github.com/salesforcecli/plugin-source/compare/v1.8.10...v1.8.11) (2022-02-03) - ### Bug Fixes -* temporarily disable async deploy NUTs ([#420](https://github.com/salesforcecli/plugin-source/issues/420)) ([e4e2d76](https://github.com/salesforcecli/plugin-source/commit/e4e2d7615272cb45fda5a4ee2694aaaae92fbf65)) - - +- temporarily disable async deploy NUTs ([#420](https://github.com/salesforcecli/plugin-source/issues/420)) ([e4e2d76](https://github.com/salesforcecli/plugin-source/commit/e4e2d7615272cb45fda5a4ee2694aaaae92fbf65)) ## [1.8.10](https://github.com/salesforcecli/plugin-source/compare/v1.8.9...v1.8.10) (2022-02-02) - - ## [1.8.9](https://github.com/salesforcecli/plugin-source/compare/v1.8.8...v1.8.9) (2022-02-01) - ### Bug Fixes -* bump lots of dependencies ([#416](https://github.com/salesforcecli/plugin-source/issues/416)) ([d242a59](https://github.com/salesforcecli/plugin-source/commit/d242a595011b8da74f2b1da3afac56f6801214bb)) - - +- bump lots of dependencies ([#416](https://github.com/salesforcecli/plugin-source/issues/416)) ([d242a59](https://github.com/salesforcecli/plugin-source/commit/d242a595011b8da74f2b1da3afac56f6801214bb)) ## [1.8.8](https://github.com/salesforcecli/plugin-source/compare/v1.8.7...v1.8.8) (2022-01-31) - ### Bug Fixes -* Add CFT/COT NUTs ([#415](https://github.com/salesforcecli/plugin-source/issues/415)) ([720e6ef](https://github.com/salesforcecli/plugin-source/commit/720e6efdddc396913c08b8e517edc66a2c804213)) - - +- Add CFT/COT NUTs ([#415](https://github.com/salesforcecli/plugin-source/issues/415)) ([720e6ef](https://github.com/salesforcecli/plugin-source/commit/720e6efdddc396913c08b8e517edc66a2c804213)) ## [1.8.7](https://github.com/salesforcecli/plugin-source/compare/v1.8.6...v1.8.7) (2022-01-30) - ### Bug Fixes -* make retrieve param consistent and fix tests ([#410](https://github.com/salesforcecli/plugin-source/issues/410)) ([79108d8](https://github.com/salesforcecli/plugin-source/commit/79108d87ceb65c49c5e17955c42733c6f0d8a2e6)) - - +- make retrieve param consistent and fix tests ([#410](https://github.com/salesforcecli/plugin-source/issues/410)) ([79108d8](https://github.com/salesforcecli/plugin-source/commit/79108d87ceb65c49c5e17955c42733c6f0d8a2e6)) ## [1.8.6](https://github.com/salesforcecli/plugin-source/compare/v1.8.5...v1.8.6) (2022-01-27) - ### Bug Fixes -* add purgeondelete flag to deploy ([#394](https://github.com/salesforcecli/plugin-source/issues/394)) ([6b99f44](https://github.com/salesforcecli/plugin-source/commit/6b99f44c0fdbe9f3d398a7e98dff29d00fc02c46)) - - +- add purgeondelete flag to deploy ([#394](https://github.com/salesforcecli/plugin-source/issues/394)) ([6b99f44](https://github.com/salesforcecli/plugin-source/commit/6b99f44c0fdbe9f3d398a7e98dff29d00fc02c46)) ## [1.8.5](https://github.com/salesforcecli/plugin-source/compare/v1.8.4...v1.8.5) (2022-01-25) - - ## [1.8.4](https://github.com/salesforcecli/plugin-source/compare/v1.8.3...v1.8.4) (2022-01-20) - - ## [1.8.3](https://github.com/salesforcecli/plugin-source/compare/v1.8.2...v1.8.3) (2022-01-20) - - ## [1.8.2](https://github.com/salesforcecli/plugin-source/compare/v1.8.1...v1.8.2) (2022-01-20) - ### Bug Fixes -* include correct username for deploy:report in async deploy ([#392](https://github.com/salesforcecli/plugin-source/issues/392)) ([f58ff25](https://github.com/salesforcecli/plugin-source/commit/f58ff251c60b18391374de7a16f732540515d524)) - - +- include correct username for deploy:report in async deploy ([#392](https://github.com/salesforcecli/plugin-source/issues/392)) ([f58ff25](https://github.com/salesforcecli/plugin-source/commit/f58ff251c60b18391374de7a16f732540515d524)) ## [1.8.1](https://github.com/salesforcecli/plugin-source/compare/v1.8.0...v1.8.1) (2022-01-19) - ### Bug Fixes -* missing quotes in --help for source:retrieve ([#393](https://github.com/salesforcecli/plugin-source/issues/393)) ([2c1e5c6](https://github.com/salesforcecli/plugin-source/commit/2c1e5c6157aed2c1d855af8f2c0a1ebf4478dc23)) - - +- missing quotes in --help for source:retrieve ([#393](https://github.com/salesforcecli/plugin-source/issues/393)) ([2c1e5c6](https://github.com/salesforcecli/plugin-source/commit/2c1e5c6157aed2c1d855af8f2c0a1ebf4478dc23)) # [1.8.0](https://github.com/salesforcecli/plugin-source/compare/v1.6.2...v1.8.0) (2022-01-13) - ### Bug Fixes -* add variable polling times based on comp. set ([#360](https://github.com/salesforcecli/plugin-source/issues/360)) ([4a839ff](https://github.com/salesforcecli/plugin-source/commit/4a839ff7f9f429a723c54baf6c9cb65139eadf43)) -* update --testlevel RunLocalTests --help to say that unlocked packages are also excluded ([#384](https://github.com/salesforcecli/plugin-source/issues/384)) ([5f0ad44](https://github.com/salesforcecli/plugin-source/commit/5f0ad449a6880d761a233c3191e3759a6c0b72cc)) - +- add variable polling times based on comp. set ([#360](https://github.com/salesforcecli/plugin-source/issues/360)) ([4a839ff](https://github.com/salesforcecli/plugin-source/commit/4a839ff7f9f429a723c54baf6c9cb65139eadf43)) +- update --testlevel RunLocalTests --help to say that unlocked packages are also excluded ([#384](https://github.com/salesforcecli/plugin-source/issues/384)) ([5f0ad44](https://github.com/salesforcecli/plugin-source/commit/5f0ad449a6880d761a233c3191e3759a6c0b72cc)) ### Features -* concise flag on status to omit ignored files ([#382](https://github.com/salesforcecli/plugin-source/issues/382)) ([2dcbac8](https://github.com/salesforcecli/plugin-source/commit/2dcbac81e57d056e82835c785bc5a5dc98a255a4)) -* mdapi deploy/report commands ([8068ff0](https://github.com/salesforcecli/plugin-source/commit/8068ff07213541a5823d5908bc831f92e89aa122)) - +- concise flag on status to omit ignored files ([#382](https://github.com/salesforcecli/plugin-source/issues/382)) ([2dcbac8](https://github.com/salesforcecli/plugin-source/commit/2dcbac81e57d056e82835c785bc5a5dc98a255a4)) +- mdapi deploy/report commands ([8068ff0](https://github.com/salesforcecli/plugin-source/commit/8068ff07213541a5823d5908bc831f92e89aa122)) ### Reverts -* Revert "chore: sync .gitignore [skip-validate-pr] (#352)" (#359) ([3d88a10](https://github.com/salesforcecli/plugin-source/commit/3d88a1058bd8bf365dbb9903a912b01c0bfaea39)), closes [#352](https://github.com/salesforcecli/plugin-source/issues/352) [#359](https://github.com/salesforcecli/plugin-source/issues/359) - - +- Revert "chore: sync .gitignore [skip-validate-pr] (#352)" (#359) ([3d88a10](https://github.com/salesforcecli/plugin-source/commit/3d88a1058bd8bf365dbb9903a912b01c0bfaea39)), closes [#352](https://github.com/salesforcecli/plugin-source/issues/352) [#359](https://github.com/salesforcecli/plugin-source/issues/359) ## [1.6.2](https://github.com/salesforcecli/plugin-source/compare/v1.6.1...v1.6.2) (2021-12-03) - ### Bug Fixes -* bump stl for customField status and pull ([#346](https://github.com/salesforcecli/plugin-source/issues/346)) ([7a657dd](https://github.com/salesforcecli/plugin-source/commit/7a657dde6dc8ffb1222034be11bd239b294b074f)) - - +- bump stl for customField status and pull ([#346](https://github.com/salesforcecli/plugin-source/issues/346)) ([7a657dd](https://github.com/salesforcecli/plugin-source/commit/7a657dde6dc8ffb1222034be11bd239b294b074f)) ## [1.6.1](https://github.com/salesforcecli/plugin-source/compare/v1.6.0...v1.6.1) (2021-12-02) - - # [1.6.0](https://github.com/salesforcecli/plugin-source/compare/v1.5.5...v1.6.0) (2021-12-02) - ### Features -* bump deps ([#339](https://github.com/salesforcecli/plugin-source/issues/339)) ([ef58621](https://github.com/salesforcecli/plugin-source/commit/ef5862195a3e5c777ab8df0d2fc5782b1d692ff0)) - - +- bump deps ([#339](https://github.com/salesforcecli/plugin-source/issues/339)) ([ef58621](https://github.com/salesforcecli/plugin-source/commit/ef5862195a3e5c777ab8df0d2fc5782b1d692ff0)) ## [1.5.5](https://github.com/salesforcecli/plugin-source/compare/v1.5.4...v1.5.5) (2021-12-01) - ### Bug Fixes -* delete bundle component and deploy 'new' bundle ([6af9705](https://github.com/salesforcecli/plugin-source/commit/6af9705f61df6743641565eb7bfbe7d20a08c495)) - - +- delete bundle component and deploy 'new' bundle ([6af9705](https://github.com/salesforcecli/plugin-source/commit/6af9705f61df6743641565eb7bfbe7d20a08c495)) ## [1.5.4](https://github.com/salesforcecli/plugin-source/compare/v1.5.3...v1.5.4) (2021-11-23) - ### Bug Fixes -* conditionally include folder ([#309](https://github.com/salesforcecli/plugin-source/issues/309)) ([6a7c936](https://github.com/salesforcecli/plugin-source/commit/6a7c9366a88dc7ea332ba3db1a5658a3b0387d6e)) - - +- conditionally include folder ([#309](https://github.com/salesforcecli/plugin-source/issues/309)) ([6a7c936](https://github.com/salesforcecli/plugin-source/commit/6a7c9366a88dc7ea332ba3db1a5658a3b0387d6e)) ## [1.5.3](https://github.com/salesforcecli/plugin-source/compare/v1.5.2...v1.5.3) (2021-11-18) - - ## [1.5.2](https://github.com/salesforcecli/plugin-source/compare/v1.5.1...v1.5.2) (2021-11-18) - - ## [1.5.1](https://github.com/salesforcecli/plugin-source/compare/v1.5.0...v1.5.1) (2021-11-18) - - # [1.5.0](https://github.com/salesforcecli/plugin-source/compare/v1.4.3...v1.5.0) (2021-11-16) - ### Features -* add mdapi:deploy:cancel command, refactor base classes to support MDAPI and SOURCE stash keys ([#301](https://github.com/salesforcecli/plugin-source/issues/301)) ([9dcc3e7](https://github.com/salesforcecli/plugin-source/commit/9dcc3e7bc1be13d1dcb0df13b3f7710407f9e977)) - - +- add mdapi:deploy:cancel command, refactor base classes to support MDAPI and SOURCE stash keys ([#301](https://github.com/salesforcecli/plugin-source/issues/301)) ([9dcc3e7](https://github.com/salesforcecli/plugin-source/commit/9dcc3e7bc1be13d1dcb0df13b3f7710407f9e977)) ## [1.4.3](https://github.com/salesforcecli/plugin-source/compare/v1.4.2...v1.4.3) (2021-11-15) - ### Bug Fixes -* add back missing help for listmetadata/describemetadata ([#295](https://github.com/salesforcecli/plugin-source/issues/295)) ([f641d83](https://github.com/salesforcecli/plugin-source/commit/f641d8311905d4aa68bcba4679674e4afa8868c1)) - - +- add back missing help for listmetadata/describemetadata ([#295](https://github.com/salesforcecli/plugin-source/issues/295)) ([f641d83](https://github.com/salesforcecli/plugin-source/commit/f641d8311905d4aa68bcba4679674e4afa8868c1)) ## [1.4.2](https://github.com/salesforcecli/plugin-source/compare/v1.4.1...v1.4.2) (2021-11-11) - ### Bug Fixes -* handle a corrupt stash.json file ([#291](https://github.com/salesforcecli/plugin-source/issues/291)) ([ac15a24](https://github.com/salesforcecli/plugin-source/commit/ac15a2433977bbd801fe54e70568bcf176ec0f1b)) - - +- handle a corrupt stash.json file ([#291](https://github.com/salesforcecli/plugin-source/issues/291)) ([ac15a24](https://github.com/salesforcecli/plugin-source/commit/ac15a2433977bbd801fe54e70568bcf176ec0f1b)) ## [1.4.1](https://github.com/salesforcecli/plugin-source/compare/v1.4.0...v1.4.1) (2021-11-11) - - # [1.4.0](https://github.com/salesforcecli/plugin-source/compare/v1.3.1...v1.4.0) (2021-11-09) - ### Features -* listmetadata and describemetadata ([b00a59a](https://github.com/salesforcecli/plugin-source/commit/b00a59a3c06cd81b121c306b6b9af3ee581a61ad)) - - +- listmetadata and describemetadata ([b00a59a](https://github.com/salesforcecli/plugin-source/commit/b00a59a3c06cd81b121c306b6b9af3ee581a61ad)) ## [1.3.1](https://github.com/salesforcecli/plugin-source/compare/v1.3.0...v1.3.1) (2021-10-28) - ### Bug Fixes -* bump SDR to 5.1.1 ([#266](https://github.com/salesforcecli/plugin-source/issues/266)) ([ff6a4f7](https://github.com/salesforcecli/plugin-source/commit/ff6a4f74401668faec6404f941ce5cf73da426ff)) - - +- bump SDR to 5.1.1 ([#266](https://github.com/salesforcecli/plugin-source/issues/266)) ([ff6a4f7](https://github.com/salesforcecli/plugin-source/commit/ff6a4f74401668faec6404f941ce5cf73da426ff)) # [1.3.0](https://github.com/salesforcecli/plugin-source/compare/v1.2.6...v1.3.0) (2021-10-28) - ### Features -* source tracking beta commands ([b871774](https://github.com/salesforcecli/plugin-source/commit/b87177498c184580db7e3bd81f164ddc77e6de0b)), closes [#253](https://github.com/salesforcecli/plugin-source/issues/253) [#251](https://github.com/salesforcecli/plugin-source/issues/251) [#230](https://github.com/salesforcecli/plugin-source/issues/230) [#260](https://github.com/salesforcecli/plugin-source/issues/260) [#259](https://github.com/salesforcecli/plugin-source/issues/259) - - +- source tracking beta commands ([b871774](https://github.com/salesforcecli/plugin-source/commit/b87177498c184580db7e3bd81f164ddc77e6de0b)), closes [#253](https://github.com/salesforcecli/plugin-source/issues/253) [#251](https://github.com/salesforcecli/plugin-source/issues/251) [#230](https://github.com/salesforcecli/plugin-source/issues/230) [#260](https://github.com/salesforcecli/plugin-source/issues/260) [#259](https://github.com/salesforcecli/plugin-source/issues/259) ## [1.2.6](https://github.com/salesforcecli/plugin-source/compare/v1.2.5...v1.2.6) (2021-10-21) - ### Bug Fixes -* use cross-env for test:nuts script ([#260](https://github.com/salesforcecli/plugin-source/issues/260)) ([76627fb](https://github.com/salesforcecli/plugin-source/commit/76627fb21c62a4fb140c87ccfc266accd79af3fd)) - - +- use cross-env for test:nuts script ([#260](https://github.com/salesforcecli/plugin-source/issues/260)) ([76627fb](https://github.com/salesforcecli/plugin-source/commit/76627fb21c62a4fb140c87ccfc266accd79af3fd)) ## [1.2.5](https://github.com/salesforcecli/plugin-source/compare/v1.2.4...v1.2.5) (2021-10-21) - - ## [1.2.4](https://github.com/salesforcecli/plugin-source/compare/v1.2.3...v1.2.4) (2021-10-12) - - ## [1.2.3](https://github.com/salesforcecli/plugin-source/compare/v1.2.1...v1.2.3) (2021-10-11) - ### Bug Fixes -* add back missing long parameter descriptions for some force:source commands ([#241](https://github.com/salesforcecli/plugin-source/issues/241)) ([d87671b](https://github.com/salesforcecli/plugin-source/commit/d87671b4987317d395873d6ef382e6a3ca2080e5)) -* remote-only deletes now supported ([#220](https://github.com/salesforcecli/plugin-source/issues/220)) ([fed3ff4](https://github.com/salesforcecli/plugin-source/commit/fed3ff496e732c6b960ae5838ea302e6b51e9029)) - - +- add back missing long parameter descriptions for some force:source commands ([#241](https://github.com/salesforcecli/plugin-source/issues/241)) ([d87671b](https://github.com/salesforcecli/plugin-source/commit/d87671b4987317d395873d6ef382e6a3ca2080e5)) +- remote-only deletes now supported ([#220](https://github.com/salesforcecli/plugin-source/issues/220)) ([fed3ff4](https://github.com/salesforcecli/plugin-source/commit/fed3ff496e732c6b960ae5838ea302e6b51e9029)) ## [1.2.1](https://github.com/salesforcecli/plugin-source/compare/v1.2.0...v1.2.1) (2021-10-05) - ### Bug Fixes -* bump deps and use internal fs ([#242](https://github.com/salesforcecli/plugin-source/issues/242)) ([6e81996](https://github.com/salesforcecli/plugin-source/commit/6e81996187f32a9ade92a48e7400601ff41602ce)) - - +- bump deps and use internal fs ([#242](https://github.com/salesforcecli/plugin-source/issues/242)) ([6e81996](https://github.com/salesforcecli/plugin-source/commit/6e81996187f32a9ade92a48e7400601ff41602ce)) # [1.2.0](https://github.com/salesforcecli/plugin-source/compare/v1.1.1...v1.2.0) (2021-09-29) - ### Features -* warning label for source:open ([#231](https://github.com/salesforcecli/plugin-source/issues/231)) ([62c7161](https://github.com/salesforcecli/plugin-source/commit/62c71614e2d0d4add9e29fda9c55dc7b639b56ea)) - - +- warning label for source:open ([#231](https://github.com/salesforcecli/plugin-source/issues/231)) ([62c7161](https://github.com/salesforcecli/plugin-source/commit/62c71614e2d0d4add9e29fda9c55dc7b639b56ea)) ## [1.1.1](https://github.com/salesforcecli/plugin-source/compare/v1.1.0...v1.1.1) (2021-09-27) - - # [1.1.0](https://github.com/salesforcecli/plugin-source/compare/v1.0.16...v1.1.0) (2021-09-24) - ### Bug Fixes -* find server errors and display them with FileResponse errors ([#210](https://github.com/salesforcecli/plugin-source/issues/210)) ([99df1ca](https://github.com/salesforcecli/plugin-source/commit/99df1ca41e83eba15646545f94c1e2ff713a6da9)) - +- find server errors and display them with FileResponse errors ([#210](https://github.com/salesforcecli/plugin-source/issues/210)) ([99df1ca](https://github.com/salesforcecli/plugin-source/commit/99df1ca41e83eba15646545f94c1e2ff713a6da9)) ### Features -* source:delete ([#199](https://github.com/salesforcecli/plugin-source/issues/199)) ([4c443c8](https://github.com/salesforcecli/plugin-source/commit/4c443c818c64829e0043932fb6fc4c0823207ebd)) - - +- source:delete ([#199](https://github.com/salesforcecli/plugin-source/issues/199)) ([4c443c8](https://github.com/salesforcecli/plugin-source/commit/4c443c818c64829e0043932fb6fc4c0823207ebd)) ## [1.0.16](https://github.com/salesforcecli/plugin-source/compare/v1.0.15...v1.0.16) (2021-09-10) - - ## [1.0.15](https://github.com/salesforcecli/plugin-source/compare/v1.0.14...v1.0.15) (2021-09-09) - ### Bug Fixes -* bump SDR to 4.4.1 ([#207](https://github.com/salesforcecli/plugin-source/issues/207)) ([d80ddf3](https://github.com/salesforcecli/plugin-source/commit/d80ddf30b7aa63129ffcbb40785c3873bc8c8f6d)) - - +- bump SDR to 4.4.1 ([#207](https://github.com/salesforcecli/plugin-source/issues/207)) ([d80ddf3](https://github.com/salesforcecli/plugin-source/commit/d80ddf30b7aa63129ffcbb40785c3873bc8c8f6d)) ## [1.0.14](https://github.com/salesforcecli/plugin-source/compare/v1.0.13...v1.0.14) (2021-09-09) - ### Bug Fixes -* release with new SDR version ([e803bc8](https://github.com/salesforcecli/plugin-source/commit/e803bc84f8a498bd6cea1f7c363fb5482b45e034)) - - +- release with new SDR version ([e803bc8](https://github.com/salesforcecli/plugin-source/commit/e803bc84f8a498bd6cea1f7c363fb5482b45e034)) ## [1.0.13](https://github.com/salesforcecli/plugin-source/compare/v1.0.12...v1.0.13) (2021-09-08) - - ## [1.0.12](https://github.com/salesforcecli/plugin-source/compare/v1.0.11...v1.0.12) (2021-08-26) - ### Bug Fixes -* force a release that updates SDR dependency ([b08ef1f](https://github.com/salesforcecli/plugin-source/commit/b08ef1f21d673353d483921a907d945f74584340)) - - +- force a release that updates SDR dependency ([b08ef1f](https://github.com/salesforcecli/plugin-source/commit/b08ef1f21d673353d483921a907d945f74584340)) ## [1.0.11](https://github.com/salesforcecli/plugin-source/compare/v1.0.10...v1.0.11) (2021-08-26) - ### Bug Fixes -* trim metadata type, and name to prevent unnecessary errors ([#179](https://github.com/salesforcecli/plugin-source/issues/179)) ([2011caa](https://github.com/salesforcecli/plugin-source/commit/2011caae414c9c4ac6e51e9d3a1da50513d3dc77)) - - +- trim metadata type, and name to prevent unnecessary errors ([#179](https://github.com/salesforcecli/plugin-source/issues/179)) ([2011caa](https://github.com/salesforcecli/plugin-source/commit/2011caae414c9c4ac6e51e9d3a1da50513d3dc77)) ## [1.0.10](https://github.com/salesforcecli/plugin-source/compare/v1.0.9...v1.0.10) (2021-08-20) - ### Bug Fixes -* wildcard metadata retrieves will now fetch source not in the project ([#177](https://github.com/salesforcecli/plugin-source/issues/177)) ([3e542c3](https://github.com/salesforcecli/plugin-source/commit/3e542c39bf9b6591c6afd4696809ea28e4b98678)) - - +- wildcard metadata retrieves will now fetch source not in the project ([#177](https://github.com/salesforcecli/plugin-source/issues/177)) ([3e542c3](https://github.com/salesforcecli/plugin-source/commit/3e542c39bf9b6591c6afd4696809ea28e4b98678)) ## [1.0.9](https://github.com/salesforcecli/plugin-source/compare/v1.0.7...v1.0.9) (2021-08-12) - ### Bug Fixes -* update command long descriptions ([#174](https://github.com/salesforcecli/plugin-source/issues/174)) ([12f1301](https://github.com/salesforcecli/plugin-source/commit/12f1301bc387f3d7ddcb5f6393bbcf20d038eb1c)) - - +- update command long descriptions ([#174](https://github.com/salesforcecli/plugin-source/issues/174)) ([12f1301](https://github.com/salesforcecli/plugin-source/commit/12f1301bc387f3d7ddcb5f6393bbcf20d038eb1c)) ## [1.0.7](https://github.com/salesforcecli/plugin-source/compare/v1.0.6...v1.0.7) (2021-08-05) - ### Bug Fixes -* bump SDR to 4.0.2 ([#169](https://github.com/salesforcecli/plugin-source/issues/169)) ([f750a3b](https://github.com/salesforcecli/plugin-source/commit/f750a3b9e841a9f6fe22e65093cb58886db69d93)) - - +- bump SDR to 4.0.2 ([#169](https://github.com/salesforcecli/plugin-source/issues/169)) ([f750a3b](https://github.com/salesforcecli/plugin-source/commit/f750a3b9e841a9f6fe22e65093cb58886db69d93)) ## [1.0.6](https://github.com/salesforcecli/plugin-source/compare/v1.0.5...v1.0.6) (2021-07-30) - - ## [1.0.5](https://github.com/salesforcecli/plugin-source/compare/v1.0.3...v1.0.5) (2021-07-29) - ### Bug Fixes -* add verbose test detail when deploying with tests ([#151](https://github.com/salesforcecli/plugin-source/issues/151)) ([1485c0e](https://github.com/salesforcecli/plugin-source/commit/1485c0e47cba4faf22f0420a561f8986e229ada0)) -* bump to 1.0.5 ([#160](https://github.com/salesforcecli/plugin-source/issues/160)) ([b0716cf](https://github.com/salesforcecli/plugin-source/commit/b0716cf0096727137ecfaa1e9e687278d0a046fd)) -* missing metadata type error matches toolbelt ([#155](https://github.com/salesforcecli/plugin-source/issues/155)) ([45ec6d0](https://github.com/salesforcecli/plugin-source/commit/45ec6d069b7d50642daccb3214e6ae8d0bdb6db1)) - - +- add verbose test detail when deploying with tests ([#151](https://github.com/salesforcecli/plugin-source/issues/151)) ([1485c0e](https://github.com/salesforcecli/plugin-source/commit/1485c0e47cba4faf22f0420a561f8986e229ada0)) +- bump to 1.0.5 ([#160](https://github.com/salesforcecli/plugin-source/issues/160)) ([b0716cf](https://github.com/salesforcecli/plugin-source/commit/b0716cf0096727137ecfaa1e9e687278d0a046fd)) +- missing metadata type error matches toolbelt ([#155](https://github.com/salesforcecli/plugin-source/issues/155)) ([45ec6d0](https://github.com/salesforcecli/plugin-source/commit/45ec6d069b7d50642daccb3214e6ae8d0bdb6db1)) ## [1.0.3](https://github.com/salesforcecli/plugin-source/compare/v1.0.2...v1.0.3) (2021-07-28) - ### Bug Fixes -* deploy:report now respects the wait flag ([#153](https://github.com/salesforcecli/plugin-source/issues/153)) ([c194f7c](https://github.com/salesforcecli/plugin-source/commit/c194f7c6907074fef8ac2b4e450c511966b83f5f)) - - +- deploy:report now respects the wait flag ([#153](https://github.com/salesforcecli/plugin-source/issues/153)) ([c194f7c](https://github.com/salesforcecli/plugin-source/commit/c194f7c6907074fef8ac2b4e450c511966b83f5f)) ## [1.0.2](https://github.com/salesforcecli/plugin-source/compare/v1.0.1...v1.0.2) (2021-07-26) - ### Bug Fixes -* throw deploy error when missing required params ([#150](https://github.com/salesforcecli/plugin-source/issues/150)) ([234c596](https://github.com/salesforcecli/plugin-source/commit/234c5968b31dc620dcdb318dccbcc1dcc1e11fde)) - - +- throw deploy error when missing required params ([#150](https://github.com/salesforcecli/plugin-source/issues/150)) ([234c596](https://github.com/salesforcecli/plugin-source/commit/234c5968b31dc620dcdb318dccbcc1dcc1e11fde)) ## [1.0.1](https://github.com/salesforcecli/plugin-source/compare/v1.0.0...v1.0.1) (2021-07-26) - ### Bug Fixes -* minor package fixes ([#152](https://github.com/salesforcecli/plugin-source/issues/152)) ([5aa593d](https://github.com/salesforcecli/plugin-source/commit/5aa593d2e20297c1b928b828679de9c3ea4809e6)) - - +- minor package fixes ([#152](https://github.com/salesforcecli/plugin-source/issues/152)) ([5aa593d](https://github.com/salesforcecli/plugin-source/commit/5aa593d2e20297c1b928b828679de9c3ea4809e6)) # [1.0.0](https://github.com/salesforcecli/plugin-source/compare/v0.1.22...v1.0.0) (2021-07-22) - ### Bug Fixes -* deploy errors are reported properly ([#146](https://github.com/salesforcecli/plugin-source/issues/146)) ([08fbbdd](https://github.com/salesforcecli/plugin-source/commit/08fbbdd2c919b1000fcdb253d9d63babf643ded1)) -* retrieve package names output ([#149](https://github.com/salesforcecli/plugin-source/issues/149)) ([7350488](https://github.com/salesforcecli/plugin-source/commit/7350488f2ac7e7d0fa1c0ffef58c7b60d74fb423)) -* set sourceApiVersion on the ComponentSet ([#147](https://github.com/salesforcecli/plugin-source/issues/147)) ([46c15ba](https://github.com/salesforcecli/plugin-source/commit/46c15ba5d5f783a09002c81870a155d0691fd162)) - - +- deploy errors are reported properly ([#146](https://github.com/salesforcecli/plugin-source/issues/146)) ([08fbbdd](https://github.com/salesforcecli/plugin-source/commit/08fbbdd2c919b1000fcdb253d9d63babf643ded1)) +- retrieve package names output ([#149](https://github.com/salesforcecli/plugin-source/issues/149)) ([7350488](https://github.com/salesforcecli/plugin-source/commit/7350488f2ac7e7d0fa1c0ffef58c7b60d74fb423)) +- set sourceApiVersion on the ComponentSet ([#147](https://github.com/salesforcecli/plugin-source/issues/147)) ([46c15ba](https://github.com/salesforcecli/plugin-source/commit/46c15ba5d5f783a09002c81870a155d0691fd162)) ## [0.1.22](https://github.com/salesforcecli/plugin-source/compare/v0.1.21...v0.1.22) (2021-06-28) - ### Bug Fixes -* display retrieve warnings ([#121](https://github.com/salesforcecli/plugin-source/issues/121)) ([a2330ed](https://github.com/salesforcecli/plugin-source/commit/a2330edb51408a91169608a5d518423dd919231b)) - - +- display retrieve warnings ([#121](https://github.com/salesforcecli/plugin-source/issues/121)) ([a2330ed](https://github.com/salesforcecli/plugin-source/commit/a2330edb51408a91169608a5d518423dd919231b)) ## [0.1.21](https://github.com/salesforcecli/plugin-source/compare/v0.1.20...v0.1.21) (2021-06-24) - ### Bug Fixes -* postretrieve hook payload is now the file responses ([#120](https://github.com/salesforcecli/plugin-source/issues/120)) ([a505389](https://github.com/salesforcecli/plugin-source/commit/a50538905a9bb02192c9803fec49000baf6a588f)) - - +- postretrieve hook payload is now the file responses ([#120](https://github.com/salesforcecli/plugin-source/issues/120)) ([a505389](https://github.com/salesforcecli/plugin-source/commit/a50538905a9bb02192c9803fec49000baf6a588f)) ## [0.1.20](https://github.com/salesforcecli/plugin-source/compare/v0.1.19...v0.1.20) (2021-06-17) - ### Bug Fixes -* temporary polling fix ([#114](https://github.com/salesforcecli/plugin-source/issues/114)) ([6c6a3ab](https://github.com/salesforcecli/plugin-source/commit/6c6a3ab6b1a4e36efa974627bc944e37e875c3d6)) - - +- temporary polling fix ([#114](https://github.com/salesforcecli/plugin-source/issues/114)) ([6c6a3ab](https://github.com/salesforcecli/plugin-source/commit/6c6a3ab6b1a4e36efa974627bc944e37e875c3d6)) ## [0.1.19](https://github.com/salesforcecli/plugin-source/compare/v0.0.19...v0.1.19) (2021-06-12) - ### Features -* add support for async deploys ([#89](https://github.com/salesforcecli/plugin-source/issues/89)) ([e7d7215](https://github.com/salesforcecli/plugin-source/commit/e7d721561542baab8abcf6a8d482e7bb9653176a)), closes [#108](https://github.com/salesforcecli/plugin-source/issues/108) [#84](https://github.com/salesforcecli/plugin-source/issues/84) [#85](https://github.com/salesforcecli/plugin-source/issues/85) [#88](https://github.com/salesforcecli/plugin-source/issues/88) [#80](https://github.com/salesforcecli/plugin-source/issues/80) [#90](https://github.com/salesforcecli/plugin-source/issues/90) [#105](https://github.com/salesforcecli/plugin-source/issues/105) [#106](https://github.com/salesforcecli/plugin-source/issues/106) - - +- add support for async deploys ([#89](https://github.com/salesforcecli/plugin-source/issues/89)) ([e7d7215](https://github.com/salesforcecli/plugin-source/commit/e7d721561542baab8abcf6a8d482e7bb9653176a)), closes [#108](https://github.com/salesforcecli/plugin-source/issues/108) [#84](https://github.com/salesforcecli/plugin-source/issues/84) [#85](https://github.com/salesforcecli/plugin-source/issues/85) [#88](https://github.com/salesforcecli/plugin-source/issues/88) [#80](https://github.com/salesforcecli/plugin-source/issues/80) [#90](https://github.com/salesforcecli/plugin-source/issues/90) [#105](https://github.com/salesforcecli/plugin-source/issues/105) [#106](https://github.com/salesforcecli/plugin-source/issues/106) ## [0.0.19](https://github.com/salesforcecli/plugin-source/compare/v0.0.18...v0.0.19) (2021-06-10) - - ## [0.0.18](https://github.com/salesforcecli/plugin-source/compare/v0.0.17...v0.0.18) (2021-06-09) - - ## [0.0.17](https://github.com/salesforcecli/plugin-source/compare/v0.0.16...v0.0.17) (2021-06-03) - - ## [0.0.16](https://github.com/salesforcecli/plugin-source/compare/v0.0.15...v0.0.16) (2021-05-20) - - ## [0.0.15](https://github.com/salesforcecli/plugin-source/compare/v0.0.14...v0.0.15) (2021-05-07) - - ## [0.0.14](https://github.com/salesforcecli/plugin-source/compare/v0.0.13...v0.0.14) (2021-05-04) - ### Bug Fixes -* support hooks for deployRecentValidation and async deploys ([#75](https://github.com/salesforcecli/plugin-source/issues/75)) ([ac787f9](https://github.com/salesforcecli/plugin-source/commit/ac787f9f8238bd09d44878a6c9994384a5c567c7)) - - +- support hooks for deployRecentValidation and async deploys ([#75](https://github.com/salesforcecli/plugin-source/issues/75)) ([ac787f9](https://github.com/salesforcecli/plugin-source/commit/ac787f9f8238bd09d44878a6c9994384a5c567c7)) ## [0.0.13](https://github.com/salesforcecli/plugin-source/compare/v0.0.12...v0.0.13) (2021-05-04) - ### Bug Fixes -* deploy output fixes ([#74](https://github.com/salesforcecli/plugin-source/issues/74)) ([d1bb8be](https://github.com/salesforcecli/plugin-source/commit/d1bb8be605458aea81503c1e5bc6974fe03c0ec6)) - - +- deploy output fixes ([#74](https://github.com/salesforcecli/plugin-source/issues/74)) ([d1bb8be](https://github.com/salesforcecli/plugin-source/commit/d1bb8be605458aea81503c1e5bc6974fe03c0ec6)) ## [0.0.12](https://github.com/salesforcecli/plugin-source/compare/v0.0.11...v0.0.12) (2021-05-01) - - ## [0.0.11](https://github.com/salesforcecli/plugin-source/compare/v0.0.10...v0.0.11) (2021-04-29) - ### Bug Fixes -* add NUT testing LWC bug ([#70](https://github.com/salesforcecli/plugin-source/issues/70)) ([d6cb456](https://github.com/salesforcecli/plugin-source/commit/d6cb456cdf127e7e896511b8af7606fce25973cb)) - - +- add NUT testing LWC bug ([#70](https://github.com/salesforcecli/plugin-source/issues/70)) ([d6cb456](https://github.com/salesforcecli/plugin-source/commit/d6cb456cdf127e7e896511b8af7606fce25973cb)) ## [0.0.10](https://github.com/salesforcecli/plugin-source/compare/v0.0.9...v0.0.10) (2021-04-23) - ### Bug Fixes -* new hooks, updated tests ([#69](https://github.com/salesforcecli/plugin-source/issues/69)) ([81e1058](https://github.com/salesforcecli/plugin-source/commit/81e10581456ceccb4b3e07f3d1310bb18bef25ff)) - - +- new hooks, updated tests ([#69](https://github.com/salesforcecli/plugin-source/issues/69)) ([81e1058](https://github.com/salesforcecli/plugin-source/commit/81e10581456ceccb4b3e07f3d1310bb18bef25ff)) ## [0.0.9](https://github.com/salesforcecli/plugin-source/compare/v0.0.8...v0.0.9) (2021-04-13) - - ## [0.0.8](https://github.com/salesforcecli/plugin-source/compare/v0.0.7...v0.0.8) (2021-04-13) - ### Features -* support split custom labels ([#62](https://github.com/salesforcecli/plugin-source/issues/62)) ([ab290a7](https://github.com/salesforcecli/plugin-source/commit/ab290a78fcdb5e4d8da2fbdcfc3e49e783e848ac)) - - +- support split custom labels ([#62](https://github.com/salesforcecli/plugin-source/issues/62)) ([ab290a7](https://github.com/salesforcecli/plugin-source/commit/ab290a78fcdb5e4d8da2fbdcfc3e49e783e848ac)) ## [0.0.7](https://github.com/salesforcecli/plugin-source/compare/v0.0.6...v0.0.7) (2021-04-09) - ### Bug Fixes -* add deploy:cancel ([#66](https://github.com/salesforcecli/plugin-source/issues/66)) ([1e673a2](https://github.com/salesforcecli/plugin-source/commit/1e673a28943d306f85baa1728e9f438b570cc0e3)) - - +- add deploy:cancel ([#66](https://github.com/salesforcecli/plugin-source/issues/66)) ([1e673a2](https://github.com/salesforcecli/plugin-source/commit/1e673a28943d306f85baa1728e9f438b570cc0e3)) ## [0.0.6](https://github.com/salesforcecli/plugin-source/compare/v0.0.5...v0.0.6) (2021-04-09) - ### Bug Fixes -* add progress bar to deploy ([#65](https://github.com/salesforcecli/plugin-source/issues/65)) ([df2f5e0](https://github.com/salesforcecli/plugin-source/commit/df2f5e0de2dea2d509d4b0a3c0ceae8cc75411b9)) - - +- add progress bar to deploy ([#65](https://github.com/salesforcecli/plugin-source/issues/65)) ([df2f5e0](https://github.com/salesforcecli/plugin-source/commit/df2f5e0de2dea2d509d4b0a3c0ceae8cc75411b9)) ## [0.0.5](https://github.com/salesforcecli/plugin-source/compare/v0.0.4...v0.0.5) (2021-04-07) - ### Bug Fixes -* add convert command ([#64](https://github.com/salesforcecli/plugin-source/issues/64)) ([26e36b2](https://github.com/salesforcecli/plugin-source/commit/26e36b22f0402b9927834ecda63f24dc65f66d96)) - - +- add convert command ([#64](https://github.com/salesforcecli/plugin-source/issues/64)) ([26e36b2](https://github.com/salesforcecli/plugin-source/commit/26e36b22f0402b9927834ecda63f24dc65f66d96)) ## [0.0.4](https://github.com/salesforcecli/plugin-source/compare/v0.0.3...v0.0.4) (2021-04-05) - - ## [0.0.3](https://github.com/salesforcecli/plugin-source/compare/v0.0.2...v0.0.3) (2021-04-02) - - ## [0.0.2](https://github.com/salesforcecli/plugin-source/compare/v0.0.1...v0.0.2) (2021-03-03) - ### Bug Fixes -* add initial NUTs, u-tests ([ca2076c](https://github.com/salesforcecli/plugin-source/commit/ca2076ca7ee1c9b0dcd23e096569006e33ecd149)) -* add retrieve via packageNames param ([2fb3217](https://github.com/salesforcecli/plugin-source/commit/2fb32170044d3d39295f2006ab6ab73a09260b43)) -* add wait to retrieve, move min wait and default wait to static members ([74a3cdd](https://github.com/salesforcecli/plugin-source/commit/74a3cddcb3d2688068f856d767e08b59d83d8adf)) -* deploy first pass ([c6665ab](https://github.com/salesforcecli/plugin-source/commit/c6665abc3fcbf381ccbdc87f40bc97b959a0d2f0)) -* fix sorting logic ([70876e3](https://github.com/salesforcecli/plugin-source/commit/70876e3edb2f2a5169a29e2ede011608fac81bc0)) -* fixed some of Steve's comments ([4596da6](https://github.com/salesforcecli/plugin-source/commit/4596da6863866236c890a993fd111ff58a092aa9)) -* match library changes for deploy ([abba216](https://github.com/salesforcecli/plugin-source/commit/abba216ffb323111837e1621a7e4ef92525eb404)) -* remove packagename, change some types ([b1d8b82](https://github.com/salesforcecli/plugin-source/commit/b1d8b82533e0df0b8b9d13306bbc1c0c7cbbfbd1)) -* source:retrieve working as a user, json and hook info wrong, missing tests ([7828c3f](https://github.com/salesforcecli/plugin-source/commit/7828c3fa64515b71c1ec6641efd79cdfe10b40da)) - - +- add initial NUTs, u-tests ([ca2076c](https://github.com/salesforcecli/plugin-source/commit/ca2076ca7ee1c9b0dcd23e096569006e33ecd149)) +- add retrieve via packageNames param ([2fb3217](https://github.com/salesforcecli/plugin-source/commit/2fb32170044d3d39295f2006ab6ab73a09260b43)) +- add wait to retrieve, move min wait and default wait to static members ([74a3cdd](https://github.com/salesforcecli/plugin-source/commit/74a3cddcb3d2688068f856d767e08b59d83d8adf)) +- deploy first pass ([c6665ab](https://github.com/salesforcecli/plugin-source/commit/c6665abc3fcbf381ccbdc87f40bc97b959a0d2f0)) +- fix sorting logic ([70876e3](https://github.com/salesforcecli/plugin-source/commit/70876e3edb2f2a5169a29e2ede011608fac81bc0)) +- fixed some of Steve's comments ([4596da6](https://github.com/salesforcecli/plugin-source/commit/4596da6863866236c890a993fd111ff58a092aa9)) +- match library changes for deploy ([abba216](https://github.com/salesforcecli/plugin-source/commit/abba216ffb323111837e1621a7e4ef92525eb404)) +- remove packagename, change some types ([b1d8b82](https://github.com/salesforcecli/plugin-source/commit/b1d8b82533e0df0b8b9d13306bbc1c0c7cbbfbd1)) +- source:retrieve working as a user, json and hook info wrong, missing tests ([7828c3f](https://github.com/salesforcecli/plugin-source/commit/7828c3fa64515b71c1ec6641efd79cdfe10b40da)) ## [0.0.1](https://github.com/salesforcecli/plugin-source/compare/598ff29125185b1644fc5c009bcb4cf56115fb31...v0.0.1) (2021-02-08) - ### Bug Fixes -* add command files, test files, message files, remove template ([598ff29](https://github.com/salesforcecli/plugin-source/commit/598ff29125185b1644fc5c009bcb4cf56115fb31)) - - - +- add command files, test files, message files, remove template ([598ff29](https://github.com/salesforcecli/plugin-source/commit/598ff29125185b1644fc5c009bcb4cf56115fb31)) diff --git a/command-snapshot.json b/command-snapshot.json index 585adad36..2b8071214 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -2,20 +2,14 @@ { "command": "force", "plugin": "@salesforce/plugin-source", - "flags": ["json", "loglevel"], + "flags": ["json"], "alias": [] }, - { - "command": "force:mdapi:convert", - "plugin": "@salesforce/plugin-source", - "flags": ["json", "loglevel", "manifest", "metadata", "metadatapath", "outputdir", "rootdir"], - "alias": ["force:mdapi:beta:convert"] - }, { "command": "force:mdapi:deploy", "plugin": "@salesforce/plugin-source", "flags": [ - "apiversion", + "api-version", "checkonly", "concise", "coverageformatters", @@ -30,26 +24,26 @@ "runtests", "singlepackage", "soapdeploy", - "targetusername", + "target-org", "testlevel", "validateddeployrequestid", "verbose", "wait", "zipfile" ], - "alias": ["force:mdapi:beta:deploy"] + "alias": [] }, { "command": "force:mdapi:deploy:cancel", "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "jobid", "json", "loglevel", "targetusername", "wait"], + "flags": ["api-version", "jobid", "json", "loglevel", "target-org", "wait"], "alias": [] }, { "command": "force:mdapi:deploy:report", "plugin": "@salesforce/plugin-source", "flags": [ - "apiversion", + "api-version", "concise", "coverageformatters", "jobid", @@ -57,11 +51,11 @@ "junit", "loglevel", "resultsdir", - "targetusername", + "target-org", "verbose", "wait" ], - "alias": ["force:mdapi:beta:deploy:report"] + "alias": [] }, { "command": "force:mdapi:retrieve", @@ -74,63 +68,37 @@ "retrievetargetdir", "singlepackage", "sourcedir", - "targetusername", + "target-org", "unpackaged", "unzip", "verbose", "wait", "zipfilename" ], - "alias": ["force:mdapi:beta:retrieve"] + "alias": [] }, { "command": "force:mdapi:retrieve:report", "plugin": "@salesforce/plugin-source", "flags": [ - "apiversion", + "api-version", "jobid", "json", "loglevel", "retrievetargetdir", - "targetusername", + "target-org", "unzip", "verbose", "wait", "zipfilename" ], - "alias": ["force:mdapi:beta:retrieve:report"] - }, - { - "command": "force:source:convert", - "plugin": "@salesforce/plugin-source", - "flags": ["json", "loglevel", "manifest", "metadata", "outputdir", "packagename", "rootdir", "sourcepath"], - "alias": [] - }, - { - "command": "force:source:delete", - "plugin": "@salesforce/plugin-source", - "flags": [ - "apiversion", - "checkonly", - "forceoverwrite", - "json", - "loglevel", - "metadata", - "noprompt", - "sourcepath", - "targetusername", - "testlevel", - "tracksource", - "verbose", - "wait" - ], "alias": [] }, { "command": "force:source:deploy", "plugin": "@salesforce/plugin-source", "flags": [ - "apiversion", + "api-version", "checkonly", "coverageformatters", "forceoverwrite", @@ -148,7 +116,7 @@ "runtests", "soapdeploy", "sourcepath", - "targetusername", + "target-org", "testlevel", "tracksource", "validateddeployrequestid", @@ -160,65 +128,43 @@ { "command": "force:source:deploy:cancel", "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "jobid", "json", "loglevel", "targetusername", "wait"], + "flags": ["api-version", "jobid", "json", "loglevel", "target-org", "wait"], "alias": [] }, { "command": "force:source:deploy:report", "plugin": "@salesforce/plugin-source", "flags": [ - "apiversion", + "api-version", "coverageformatters", "jobid", "json", "junit", "loglevel", "resultsdir", - "targetusername", + "target-org", "verbose", "wait" ], "alias": [] }, - { - "command": "force:source:ignored:list", - "plugin": "@salesforce/plugin-source", - "flags": ["json", "loglevel", "sourcepath"], - "alias": [] - }, - { - "command": "force:source:manifest:create", - "plugin": "@salesforce/plugin-source", - "flags": [ - "apiversion", - "fromorg", - "includepackages", - "json", - "loglevel", - "manifestname", - "manifesttype", - "metadata", - "outputdir", - "sourcepath" - ], - "alias": [] - }, { "command": "force:source:pull", "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "forceoverwrite", "json", "loglevel", "targetusername", "wait"], - "alias": ["force:source:beta:pull"] + "flags": ["api-version", "forceoverwrite", "json", "loglevel", "target-org", "verbose", "wait"], + "alias": [] }, { "command": "force:source:push", "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "forceoverwrite", "ignorewarnings", "json", "loglevel", "quiet", "targetusername", "wait"], - "alias": ["force:source:beta:push"] + "flags": ["api-version", "forceoverwrite", "ignorewarnings", "json", "loglevel", "quiet", "target-org", "wait"], + "alias": [] }, { "command": "force:source:retrieve", "plugin": "@salesforce/plugin-source", "flags": [ + "api-version", "apiversion", "forceoverwrite", "json", @@ -228,7 +174,7 @@ "packagenames", "retrievetargetdir", "sourcepath", - "targetusername", + "target-org", "tracksource", "verbose", "wait" @@ -238,19 +184,7 @@ { "command": "force:source:status", "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "concise", "json", "local", "loglevel", "remote", "targetusername"], - "alias": ["force:source:beta:status"] - }, - { - "command": "force:source:tracking:clear", - "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "json", "loglevel", "noprompt", "targetusername"], - "alias": ["force:source:beta:tracking:clear"] - }, - { - "command": "force:source:tracking:reset", - "plugin": "@salesforce/plugin-source", - "flags": ["apiversion", "json", "loglevel", "noprompt", "revision", "targetusername"], - "alias": ["force:source:beta:tracking:reset"] + "flags": ["api-version", "concise", "json", "local", "loglevel", "remote", "target-org"], + "alias": [] } ] diff --git a/messages/cancel.json b/messages/cancel.json deleted file mode 100644 index a3136babe..000000000 --- a/messages/cancel.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "description": "cancel a source deployment\n Use this command to cancel a specified asynchronous source deployment. You can also specify a wait time (in minutes) to check for updates to the canceled deploy status.\n\nTo run the command asynchronously, set --wait to 0, which immediately returns the job ID. This way, you can continue to use the CLI.\nTo check the status of the job, use force:source:deploy:report.", - "examples": [ - "Deploy a directory of files to the org\n $ sfdx force:source:deploy -d \nNow cancel this deployment and wait two minutes\n $ sfdx force:source:deploy:cancel -w 2", - "If you have multiple deployments in progress and want to cancel a specific one, specify the job ID\n $ sfdx force:source:deploy:cancel -i \nCheck the status of the cancel job\n $ sfdx force:source:deploy:report" - ], - "flags": { - "wait": "wait time for command to finish in minutes", - "jobid": "job ID of the deployment you want to cancel; defaults to your most recent CLI deployment if not specified" - }, - "flagsLong": { - "wait": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. " - }, - "CancelFailed": "The cancel command failed due to: %s" -} diff --git a/messages/cancel.md b/messages/cancel.md new file mode 100644 index 000000000..276c0348e --- /dev/null +++ b/messages/cancel.md @@ -0,0 +1,39 @@ +# summary + +Cancel a source deployment. + +# description + +Use this command to cancel a specified asynchronous source deployment. You can also specify a wait time (in minutes) to check for updates to the canceled deploy status. + +To run the command asynchronously, set --wait to 0, which immediately returns the job ID. This way, you can continue to use the CLI. To check the status of the job, use "force source deploy report". + +# examples + +- Cancel a deployment and wait two minutes: + + <%= config.bin %> <%= command.id %> --wait 2 + +- If you have multiple deployments in progress and want to cancel a specific one, specify the job ID: + + <%= config.bin %> <%= command.id %> --jobid + +# flags.wait.summary + +Number of minutes to wait for the command to complete and display results. + +# flags.jobid.summary + +Job ID of the deployment you want to cancel; defaults to your most recent CLI deployment if not specified. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# CancelFailed + +The cancel command failed due to: %s + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/convert.json b/messages/convert.json deleted file mode 100644 index f54626fe1..000000000 --- a/messages/convert.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "description": "convert source into Metadata API format \n Converts source-formatted files into metadata that you can deploy using Metadata API. \nTo convert source-formatted files into the metadata format, so that you can deploy them using Metadata API,\nrun \"sfdx force:source:convert\". Then deploy the metadata using \"sfdx force:mdapi:deploy\".\n\nTo convert Metadata API–formatted files into the source format, run \"sfdx force:mdapi:convert\".\n\nTo specify a package name that includes spaces, enclose the name in single quotes.", - "examples": [ - "$ sfdx force:source:convert -r path/to/source", - "$ sfdx force:source:convert -r path/to/source -d path/to/outputdir -n 'My Package'" - ], - "flags": { - "rootdir": "a source directory other than the default package to convert", - "outputdir": "output directory to store the Metadata API–formatted files in", - "packagename": "name of the package to associate with the metadata-formatted files", - "manifest": "file path to manifest (package.xml) of metadata types to convert.", - "sourcepath": "comma-separated list of paths to the local source files to convert", - "metadata": "comma-separated list of metadata component names to convert" - }, - "flagsLong": { - "manifest": [ - "The complete path to the manifest (package.xml) file that specifies the metadata types to convert.", - "If you specify this parameter, don’t specify --metadata or --sourcepath." - ], - "sourcepath": [ - "A comma-separated list of paths to the local source files to convert. The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all metadata types in the directory and its sub-directories).", - "If you specify this parameter, don’t specify --manifest or --metadata." - ] - }, - "success": "Source was successfully converted to Metadata API format and written to the location: %s", - "convertFailed": "Failed to convert source" -} diff --git a/messages/create.json b/messages/create.json deleted file mode 100644 index d0fb53fa8..000000000 --- a/messages/create.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "description": "create a project manifest that lists the metadata components you want to deploy or retrieve \n Create a manifest from a list of metadata components (--metadata) or from one or more local directories that contain source files (--sourcepath). You can specify either of these parameters, not both.\n\nUse --manifesttype to specify the type of manifest you want to create. The resulting manifest files have specific names, such as the standard package.xml or destructiveChanges.xml to delete metadata. Valid values for this parameter, and their respective file names, are:\n\n package : package.xml (default)\n pre : destructiveChangesPre.xml\n post : destructiveChangesPost.xml\n destroy : destructiveChanges.xml\n\nSee https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_deploy_deleting_files.htm for information about these destructive manifest files. \n\nUse --manifestname to specify a custom name for the generated manifest if the pre-defined ones don’t suit your needs. You can specify either --manifesttype or --manifestname, but not both.\n", - "examples": [ - "$ sfdx force:source:manifest:create -m ApexClass", - "$ sfdx force:source:manifest:create -m ApexClass:MyApexClass --manifesttype destroy", - "$ sfdx force:source:manifest:create --sourcepath force-app --manifestname myNewManifest", - "$ sfdx force:source:manifest:create --fromorg test@myorg.com --includepackages unlocked" - ], - "flags": { - "includepackages": "comma-separated list of package types (managed, unlocked) whose metadata is included in the manifest; by default, metadata in packages is ignored", - "fromorg": "username or alias of the org that contains the metadata components from which to build a manifest", - "manifesttype": "type of manifest to create; the type determines the name of the created file", - "manifestname": "name of a custom manifest file to create", - "outputdir": "directory to save the created manifest", - "sourcepath": "comma-separated list of paths to the local source files to include in the manifest", - "metadata": "comma-separated list of names of metadata components to include in the manifest" - }, - "success": "successfully wrote %s", - "successOutputDir": "successfully wrote %s to %s" -} diff --git a/messages/delete.json b/messages/delete.json deleted file mode 100644 index dd08a1fef..000000000 --- a/messages/delete.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "description": "delete source from your project and from a non-source-tracked org\nIMPORTANT: Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations.\n\nUse this command to delete components from orgs that don’t have source tracking.\nTo remove deleted items from scratch orgs, which have change tracking, use \"sfdx force:source:push\".", - "examples": ["$ sfdx force:source:delete -m ", "$ sfdx force:source:delete -p path/to/source"], - "flags": { - "sourcepath": "comma-separated list of source file paths to delete", - "metadata": "comma-separated list of names of metadata components to delete", - "noprompt": "do not prompt for delete confirmation", - "wait": "wait time for command to finish in minutes", - "checkonly": "validate delete command but do not delete from the org or delete files locally", - "testLevel": "deployment testing level", - "runTests": "tests to run if --testlevel RunSpecifiedTests", - "tracksource": "If the delete succeeds, update the source tracking information, similar to push", - "forceoverwrite": "ignore conflict warnings and overwrite changes to the org", - "verbose": "verbose output of delete result" - }, - "flagsLong": { - "checkonly": [ - "Validates the deleted metadata and runs all Apex tests, but prevents the deletion from being saved to the org. ", - "If you change a field type from Master-Detail to Lookup or vice versa, that change isn’t supported when using the --checkonly parameter to test a deletion (validation). This kind of change isn’t supported for test deletions to avoid the risk of data loss or corruption. If a change that isn’t supported for test deletions is included in a deletion package, the test deletion fails and issues an error.", - "If your deletion package changes a field type from Master-Detail to Lookup or vice versa, you can still validate the changes prior to deploying to Production by performing a full deletion to another test Sandbox. A full deletion includes a validation of the changes as part of the deletion process.", - "Note: A Metadata API deletion that includes Master-Detail relationships deletes all detail records in the Recycle Bin in the following cases.", - "1. For a deletion with a new Master-Detail field, soft delete (send to the Recycle Bin) all detail records before proceeding to delete the Master-Detail field, or the deletion fails. During the deletion, detail records are permanently deleted from the Recycle Bin and cannot be recovered.", - "2. For a deletion that converts a Lookup field relationship to a Master-Detail relationship, detail records must reference a master record or be soft-deleted (sent to the Recycle Bin) for the deletion to succeed. However, a successful deletion permanently deletes any detail records in the Recycle Bin." - ], - "metadata": [ - "A comma-separated list of names of metadata components to delete from your project and your org.", - "If you specify this parameter, don’t specify --sourcepath." - ], - "sourcepath": [ - "A comma-separated list of paths to the local metadata to delete. The supplied paths can be a single file (in which case the operation is applied to only one file) or a folder (in which case the operation is applied to all metadata types in the directory and its sub-directories).", - "If you specify this parameter, don’t specify --metadata." - ], - "wait": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you.", - "testLevel": [ - "Specifies which level of deployment tests to run. Valid values are:", - "NoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial orgs. This test level is the default for development environments.", - "RunLocalTests—All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers.", - "RunAllTestsInOrg—All tests in your org are run, including tests of managed packages.", - "If you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see “Running Tests in a Deployment” in the Metadata API Developer Guide." - ] - }, - "localPrompt": "This operation will delete the following files on your computer and in your org: \n%s", - "remotePrompt": "This operation will delete the following metadata in your org: \n%s", - "deployPrompt": "This operation will deploy the following: \n%s", - "areYouSure": "\n\nAre you sure you want to proceed (y/n)?", - "areYouSureCheckOnly": "\n\nAre you sure you want to proceed (this is only a check and won't actually delete anything) (y/n)?" -} diff --git a/messages/deploy.json b/messages/deploy.json deleted file mode 100644 index d539dc275..000000000 --- a/messages/deploy.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "description": "deploy source to an org\nIMPORTANT: Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations.\n\nUse this command to deploy source (metadata that’s in source format) to an org.\nTo take advantage of change tracking with scratch orgs, use \"sfdx force:source:push\".\nTo deploy metadata that’s in metadata format, use \"sfdx force:mdapi:deploy\".\n\nThe source you deploy overwrites the corresponding metadata in your org. This command does not attempt to merge your source with the versions in your org.\n\nTo run the command asynchronously, set --wait to 0, which immediately returns the job ID. This way, you can continue to use the CLI.\nTo check the status of the job, use force:source:deploy:report.\n\nIf the comma-separated list you’re supplying contains spaces, enclose the entire comma-separated list in one set of double quotes. On Windows, if the list contains commas, also enclose the entire list in one set of double quotes.\n If you use the --manifest, --predestructivechanges, or --postdestructivechanges parameters, run the force:source:manifest:create command to easily generate the different types of manifest files.", - "examples": [ - "To deploy the source files in a directory:\n\t $ sfdx force:source:deploy -p path/to/source", - "To deploy a specific Apex class and the objects whose source is in a directory: \n\t$ sfdx force:source:deploy -p \"path/to/apex/classes/MyClass.cls,path/to/source/objects\"", - "To deploy source files in a comma-separated list that contains spaces:\n $ sfdx force:source:deploy -p \"path/to/objects/MyCustomObject/fields/MyField.field-meta.xml, path/to/apex/classes\"", - "To deploy all Apex classes:\n $ sfdx force:source:deploy -m ApexClass", - "To deploy a specific Apex class:\n $ sfdx force:source:deploy -m ApexClass:MyApexClass", - "To deploy a specific Apex class and update source tracking files :\n $ sfdx force:source:deploy -m ApexClass:MyApexClass --tracksource", - "To deploy all custom objects and Apex classes:\n $ sfdx force:source:deploy -m \"CustomObject,ApexClass\"", - "To deploy all Apex classes and two specific profiles (one of which has a space in its name):\n $ sfdx force:source:deploy -m \"ApexClass, Profile:My Profile, Profile: AnotherProfile\"", - "To deploy all components listed in a manifest:\n $ sfdx force:source:deploy -x path/to/package.xml", - "To run the tests that aren’t in any managed packages as part of a deployment:\n $ sfdx force:source:deploy -m ApexClass -l RunLocalTests", - "To check whether a deployment would succeed (to prepare for Quick Deploy):\n $ sfdx force:source:deploy -m ApexClass -l RunAllTestsInOrg -c", - "To deploy an already validated deployment (Quick Deploy):\n $ sfdx force:source:deploy -q 0Af9A00000FTM6pSAH`", - "To run a destructive operation before the deploy occurs:\n $ sfdx force:source:deploy --manifest package.xml --predestructivechanges destructiveChangesPre.xml", - "To run a destructive operation after the deploy occurs:\n $ sfdx force:source:deploy --manifest package.xml --postdestructivechanges destructiveChangesPost.xml" - ], - "flags": { - "sourcePath": "comma-separated list of source file paths to deploy", - "manifest": "file path for manifest (package.xml) of components to deploy", - "metadata": "comma-separated list of metadata component names", - "wait": "wait time for command to finish in minutes", - "verbose": "verbose output of deploy result", - "checkonly": "validate deploy but don’t save to the org", - "testLevel": "deployment testing level", - "runTests": "tests to run if --testlevel RunSpecifiedTests", - "ignoreErrors": "ignore any errors and do not roll back deployment", - "ignoreWarnings": "whether a warning will allow a deployment to complete successfully", - "validateDeployRequestId": "deploy request ID of the validated deployment to run a Quick Deploy", - "soapDeploy": "deploy metadata with SOAP API instead of REST API", - "predestructivechanges": "file path for a manifest (destructiveChangesPre.xml) of components to delete before the deploy", - "postdestructivechanges": "file path for a manifest (destructiveChangesPost.xml) of components to delete after the deploy", - "tracksource": "if the deploy succeeds, update source tracking information; doesn't delete locally deleted files from org unless you also specify --predestructivechanges or --postdestructivechanges", - "forceoverwrite": "ignore conflict warnings and overwrite changes to the org", - "purgeOnDelete": "specify that deleted components in the destructive changes manifest file are immediately eligible for deletion rather than being stored in the Recycle Bin", - "junit": "output JUnit test results", - "coverageFormatters": "format of the code coverage results", - "resultsDir": "output directory for code coverage and JUnit results; defaults to the deploy ID" - }, - "flagsLong": { - "sourcePath": [ - "A comma-separated list of paths to the local source files to deploy. The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all metadata types in the directory and its sub-directories).", - "If you specify this parameter, don’t specify --manifest or --metadata." - ], - "manifest": [ - "The complete path for the manifest (package.xml) file that specifies the components to deploy. All child components are included.", - "If you specify this parameter, don’t specify --metadata or --sourcepath." - ], - "metadata": [ - "A comma-separated list of names of metadata components to deploy to the org.", - "If you specify this parameter, don’t specify --manifest or --sourcepath." - ], - "wait": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. ", - "checkonly": [ - "Validates the deployed metadata and runs all Apex tests, but prevents the deployment from being saved to the org.", - "If you change a field type from Master-Detail to Lookup or vice versa, that change isn’t supported when using the --checkonly parameter to test a deployment (validation). This kind of change isn’t supported for test deployments to avoid the risk of data loss or corruption. If a change that isn’t supported for test deployments is included in a deployment package, the test deployment fails and issues an error.", - "If your deployment package changes a field type from Master-Detail to Lookup or vice versa, you can still validate the changes prior to deploying to Production by performing a full deployment to another test Sandbox. A full deployment includes a validation of the changes as part of the deployment process.", - "Note: A Metadata API deployment that includes Master-Detail relationships deletes all detail records in the Recycle Bin in the following cases.", - "1. For a deployment with a new Master-Detail field, soft delete (send to the Recycle Bin) all detail records before proceeding to deploy the Master-Detail field, or the deployment fails. During the deployment, detail records are permanently deleted from the Recycle Bin and cannot be recovered.", - "2. For a deployment that converts a Lookup field relationship to a Master-Detail relationship, detail records must reference a master record or be soft-deleted (sent to the Recycle Bin) for the deployment to succeed. However, a successful deployment permanently deletes any detail records in the Recycle Bin." - ], - "testLevel": [ - "Specifies which level of deployment tests to run. Valid values are:", - " NoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial orgs. This test level is the default for development environments.", - " RunSpecifiedTests—Runs only the tests that you specify in the --runtests option. Code coverage requirements differ from the default coverage requirements when using this test level. Executed tests must comprise a minimum of 75% code coverage for each class and trigger in the deployment package. This coverage is computed for each class and trigger individually and is different than the overall coverage percentage.", - " RunLocalTests—All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers.", - " RunAllTestsInOrg—All tests in your org are run, including tests of managed packages.", - "If you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see “Running Tests in a Deployment” in the Metadata API Developer Guide." - ], - "runTests": "Lists the Apex classes containing the deployment tests to run. Use this parameter when you set --testlevel to RunSpecifiedTests.", - "ignoreErrors": "Ignores the deploy errors, and continues with the deploy operation. The default is false. Keep this parameter set to false when deploying to a production org. If set to true, components without errors are deployed, and components with errors are skipped.", - "ignoreWarnings": "If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. When ignoreWarnings is set to false, success is set to false, and the warning is treated like an error.", - "validateDeployRequestId": [ - "Specifies the ID of a package with recently validated components to run a Quick Deploy. Deploying a validation helps you shorten your deployment time because tests aren’t rerun. If you have a recent successful validation, you can deploy the validated components without running tests. A validation doesn’t save any components in the org. You use a validation only to check the success or failure messages that you would receive with an actual deployment. To validate your components, add the -c | --checkonly flag when you run \"sfdx force:mdapi:deploy\". This flag sets the checkOnly=\"true\" parameter for your deployment. Before deploying a recent validation, ensure that the following requirements are met:", - " 1. The components have been validated successfully for the target environment within the last 10 days.", - " 2. As part of the validation, Apex tests in the target org have passed.", - " 3. Code coverage requirements are met.", - " - If all tests in the org or all local tests are run, overall code coverage is at least 75%, and Apex triggers have some coverage.", - " - If specific tests are run with the RunSpecifiedTests test level, each class and trigger that was deployed is covered by at least 75% individually." - ] - }, - "checkOnlySuccess": "Successfully validated the deployment. %s components deployed and %s tests run.\nUse the --verbose parameter to see detailed output.", - "checkOnlySuccessVerbose": "Successfully validated the deployment.", - "deploySuccess": "Deploy Succeeded.", - "deployCanceled": "The deployment has been canceled by %s.", - "deployFailed": "Deploy failed. %s", - "asyncDeployQueued": "Deploy has been queued.", - "asyncDeployCancel": "Run sfdx force:source:deploy:cancel -i %s -u %s to cancel the deploy.", - "asyncDeployReport": "Run sfdx force:source:deploy:report -i %s -u %s to get the latest status.", - "invalidDeployId": "The provided ID is invalid, deploy IDs must start with '0Af'.", - "deployWontDelete": "You currently have files deleted locally. The deploy command will NOT delete them from your org unless you use one of the destructivechanges flags.", - "asyncCoverageJunitWarning": "You requested an async deploy with code coverage or JUnit results. The reports will be available when the deploy completes." -} diff --git a/messages/deploy.md b/messages/deploy.md new file mode 100644 index 000000000..22bab4bbc --- /dev/null +++ b/messages/deploy.md @@ -0,0 +1,276 @@ +# summary + +Deploy source to an org. + +# description + +Use this command to deploy source (metadata that’s in source format) to an org. To take advantage of change tracking with scratch orgs, use "force source push". To deploy metadata that’s in metadata format, use "force mdapi deploy". + +The source you deploy overwrites the corresponding metadata in your org. This command does not attempt to merge your source with the versions in your org. + +To run the command asynchronously, set --wait to 0, which immediately returns the job ID. This way, you can continue to use the CLI. To check the status of the job, use "force source deploy report". + +If the comma-separated list you’re supplying contains spaces, enclose the entire comma-separated list in one set of double quotes. On Windows, if the list contains commas, also enclose the entire list in one set of double quotes. + +If you use the --manifest, --predestructivechanges, or --postdestructivechanges parameters, run the "force source manifest create" command to easily generate the different types of manifest files. + +# examples + +- Deploy the source files in a directory: + + <%= config.bin %> <%= command.id %> --sourcepath path/to/source + +- Deploy a specific Apex class and the objects whose source is in a directory: + + <%= config.bin %> <%= command.id %> --sourcepath "path/to/apex/classes/MyClass.cls,path/to/source/objects" + +- Deploy source files in a comma-separated list that contains spaces: + + <%= config.bin %> <%= command.id %> --sourcepath "path/to/objects/MyCustomObject/fields/MyField.field-meta.xml, path/to/apex/classes" + +- Deploy all Apex classes: + + <%= config.bin %> <%= command.id %> --metadata ApexClass + +- Deploy a specific Apex class: + + <%= config.bin %> <%= command.id %> --metadata ApexClass:MyApexClass + +- Deploy a specific Apex class and update source tracking files : + + <%= config.bin %> <%= command.id %> --metadata ApexClass:MyApexClass --tracksource + +- Deploy all custom objects and Apex classes: + + <%= config.bin %> <%= command.id %> --metadata "CustomObject,ApexClass" + +- Deploy all Apex classes and two specific profiles (one of which has a space in its name): + + <%= config.bin %> <%= command.id %> --metadata "ApexClass, Profile:My Profile, Profile: AnotherProfile" + +- Deploy all components listed in a manifest: + + <%= config.bin %> <%= command.id %> --manifest path/to/package.xml + +- Run the tests that aren’t in any managed packages as part of a deployment: + + <%= config.bin %> <%= command.id %> --metadata ApexClass --testlevel RunLocalTests + +- Check whether a deployment would succeed (to prepare for Quick Deploy): + + <%= config.bin %> <%= command.id %> --metadata ApexClass --testlevel RunAllTestsInOrg -c + +- Deploy an already validated deployment (Quick Deploy): + + <%= config.bin %> <%= command.id %> --validateddeployrequestid 0Af9A00000FTM6pSAH` + +- Run a destructive operation before the deploy occurs: + + <%= config.bin %> <%= command.id %> --manifest package.xml --predestructivechanges destructiveChangesPre.xml + +- Run a destructive operation after the deploy occurs: + + <%= config.bin %> <%= command.id %> --manifest package.xml --postdestructivechanges destructiveChangesPost.xml + +# flags.sourcePath.summary + +Comma-separated list of source file paths to deploy. + +# flags.manifest.summary + +Complete path for the manifest (package.xml) file that specifies the components to deploy. + +# flags.metadata.summary + +Comma-separated list of metadata component names. + +# flags.wait.summary + +Wait time for command to finish in minutes. + +# flags.verbose.summary + +Specify verbose output about the deploy result. + +# flags.checkonly.summary + +Validate the deployed metadata and run all Apex tests, but don't save to the org. + +# flags.testLevel.summary + +Deployment testing level. + +# flags.runTests.summary + +Apex test classes to run if --testlevel RunSpecifiedTests. + +# flags.ignoreErrors.summary + +Ignore any errors and don't roll back deployment. + +# flags.ignoreWarnings.summary + +Allow a deployment to complete successfully even if there are warnings. + +# flags.validateDeployRequestId.summary + +Deploy request ID of the validated deployment to run a Quick Deploy. + +# flags.soapDeploy.summary + +Deploy metadata with SOAP API instead of REST API. + +# flags.predestructivechanges.summary + +File path for a manifest (destructiveChangesPre.xml) of components to delete before the deploy. + +# flags.postdestructivechanges.summary + +File path for a manifest (destructiveChangesPost.xml) of components to delete after the deploy. + +# flags.tracksource.summary + +If the deploy succeeds, update source tracking information. + +# flags.tracksource.description + +Doesn't delete locally deleted files from org unless you also specify --predestructivechanges or --postdestructivechanges. + +# flags.forceoverwrite.summary + +Ignore conflict warnings and overwrite changes to the org. + +# flags.purgeOnDelete.summary + +Specify that deleted components in the destructive changes manifest file are immediately eligible for deletion rather than being stored in the Recycle Bin. + +# flags.junit.summary + +Output JUnit test results. + +# flags.coverageFormatters.summary + +Format of the code coverage results. + +# flags.resultsDir.summary + +Output directory for code coverage and JUnit results; defaults to the deploy ID. + +# flags.sourcePath.description + +The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all metadata types in the directory and its sub-directories). + +If you specify this parameter, don’t specify --manifest or --metadata. + +# flags.manifest.description + +All child components are included. + +If you specify this parameter, don’t specify --metadata or --sourcepath. + +# flags.metadata.description + +If you specify this parameter, don’t specify --manifest or --sourcepath. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# flags.checkonly.description + +IMPORTANT: Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations. + +If you change a field type from Master-Detail to Lookup or vice versa, that change isn’t supported when using the --checkonly parameter to test a deployment (validation). This kind of change isn’t supported for test deployments to avoid the risk of data loss or corruption. If a change that isn’t supported for test deployments is included in a deployment package, the test deployment fails and issues an error. + +If your deployment package changes a field type from Master-Detail to Lookup or vice versa, you can still validate the changes prior to deploying to Production by performing a full deployment to another test Sandbox. A full deployment includes a validation of the changes as part of the deployment process. + +Note: A Metadata API deployment that includes Master-Detail relationships deletes all detail records in the Recycle Bin in the following cases. + + 1. For a deployment with a new Master-Detail field, soft delete (send to the Recycle Bin) all detail records before proceeding to deploy the Master-Detail field, or the deployment fails. During the deployment, detail records are permanently deleted from the Recycle Bin and cannot be recovered. + + 2. For a deployment that converts a Lookup field relationship to a Master-Detail relationship, detail records must reference a master record or be soft-deleted (sent to the Recycle Bin) for the deployment to succeed. However, a successful deployment permanently deletes any detail records in the Recycle Bin. + +# flags.testLevel.description + +Valid values are: + + - NoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial orgs. This test level is the default for development environments. + + - RunSpecifiedTests—Runs only the tests that you specify in the --runtests option. Code coverage requirements differ from the default coverage requirements when using this test level. Executed tests must comprise a minimum of 75% code coverage for each class and trigger in the deployment package. This coverage is computed for each class and trigger individually and is different than the overall coverage percentage. + + - RunLocalTests—All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers. + + - RunAllTestsInOrg—All tests in your org are run, including tests of managed packages. + +If you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see “Running Tests in a Deployment” in the Metadata API Developer Guide. + +# flags.ignoreErrors.description + +Keep this parameter set to false when deploying to a production org. If set to true, components without errors are deployed, and components with errors are skipped. + +# flags.ignoreWarnings.description + +If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. When ignoreWarnings is set to false, success is set to false, and the warning is treated like an error. + +# flags.validateDeployRequestId.description + +Deploying a validation helps you shorten your deployment time because tests aren’t rerun. If you have a recent successful validation, you can deploy the validated components without running tests. A validation doesn’t save any components in the org. You use a validation only to check the success or failure messages that you would receive with an actual deployment. To validate your components, add the -c | --checkonly flag when you run "force mdapi deploy". This flag sets the checkOnly="true" parameter for your deployment. Before deploying a recent validation, ensure that the following requirements are met: + + 1. The components have been validated successfully for the target environment within the last 10 days. + + 2. As part of the validation, Apex tests in the target org have passed. + + 3. Code coverage requirements are met. + + * If all tests in the org or all local tests are run, overall code coverage is at least 75%, and Apex triggers have some coverage. + + * If specific tests are run with the RunSpecifiedTests test level, each class and trigger that was deployed is covered by at least 75% individually. + +# checkOnlySuccess + +Successfully validated the deployment. %s components deployed and %s tests run. +Use the --verbose parameter to see detailed output. + +# checkOnlySuccessVerbose + +Successfully validated the deployment. + +# deploySuccess + +Deploy Succeeded. + +# deployCanceled + +The deployment has been canceled by %s. + +# deployFailed + +Deploy failed. %s + +# asyncDeployQueued + +Deploy has been queued. + +# asyncDeployCancel + +Run "force source deploy cancel -i %s -u %s" to cancel the deploy. + +# asyncDeployReport + +Run "force source deploy report -i %s -u %s" to get the latest status. + +# invalidDeployId + +The provided ID is invalid, deploy IDs must start with '0Af'. + +# deployWontDelete + +You currently have files deleted locally. The deploy command will NOT delete them from your org unless you use one of the destructivechanges Flags. + +# asyncCoverageJunitWarning + +You requested an async deploy with code coverage or JUnit results. The reports will be available when the deploy completes. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/deployCommand.json b/messages/deployCommand.json deleted file mode 100644 index d659184ce..000000000 --- a/messages/deployCommand.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "resultsDirMissing": "You must supply the --resultsdir parameter when choosing to produce code coverage or JUnit reports.", - "MissingDeployId": "No deploy ID was provided or found in deploy history.", - "invalidDeployId": "The provided ID is invalid, deploy IDs must start with '0Af'.", - "apiVersionMsgBasic": "Deploying metadata to %s using the v%s %s API", - "apiVersionMsgDetailed": "%s v%s metadata to %s using the v%s %s API" -} diff --git a/messages/deployCommand.md b/messages/deployCommand.md new file mode 100644 index 000000000..44586ff6d --- /dev/null +++ b/messages/deployCommand.md @@ -0,0 +1,19 @@ +# resultsDirMissing + +You must supply the --resultsdir parameter when choosing to produce code coverage or JUnit reports. + +# MissingDeployId + +No deploy ID was provided or found in deploy history. + +# invalidDeployId + +The provided ID is invalid, deploy IDs must start with '0Af'. + +# apiVersionMsgBasic + +Deploying metadata to %s using the v%s %s API. + +# apiVersionMsgDetailed + +%s v%s metadata to %s using the v%s %s API. diff --git a/messages/diagnostics.json b/messages/diagnostics.json deleted file mode 100644 index 74d66cfb0..000000000 --- a/messages/diagnostics.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "apiVersionMismatch": "The sourceApiVersion in sfdx-project.json doesn't match the apiVersion. The commands that deploy and retrieve source use the sourceApiVersion in this case. The version mismatch isn't a problem, as long as it's the behavior you actually want. ", - "apiVersionUnset": "Neither sourceApiVersion nor apiVersion are defined. The commands that deploy and retrieve source use the max apiVersion of the target org in this case. The issue isn't a problem, as long as it's the behavior you actually want.", - "maxApiVersionMismatch": "The max apiVersion of the default DevHub org doesn't match the max apiVersion of the default target org. This mismatch means that the default target orgs are running different API versions. Be sure you explicitly set the apiVersion when you deploy or retrieve source, or you will likely run into problems.", - "sourceApiVersionMaxMismatch": "The sourceApiVersion in sfdx-project.json doesn't match the max apiVersion of the default target org. As a result, you're not using the latest features available in API version %s. The version mismatch isn't a problem, as long as it's the behavior you actually want.", - "apiVersionMaxMismatch": "The apiVersion doesn't match the max apiVersion of the default target org. As a result, you're not using the latest features available in API version %s. The version mismatch isn't a problem, as long as it's the behavior you actually want." -} diff --git a/messages/diagnostics.md b/messages/diagnostics.md new file mode 100644 index 000000000..1d50452d5 --- /dev/null +++ b/messages/diagnostics.md @@ -0,0 +1,19 @@ +# apiVersionMismatch + +The sourceApiVersion in sfdx-project.json doesn't match the apiVersion. The commands that deploy and retrieve source use the sourceApiVersion in this case. The version mismatch isn't a problem, as long as it's the behavior you actually want. + +# apiVersionUnset + +Neither sourceApiVersion nor apiVersion are defined. The commands that deploy and retrieve source use the max apiVersion of the target org in this case. The issue isn't a problem, as long as it's the behavior you actually want. + +# maxApiVersionMismatch + +The max apiVersion of the default DevHub org doesn't match the max apiVersion of the default target org. This mismatch means that the default target orgs are running different API versions. Be sure you explicitly set the apiVersion when you deploy or retrieve source, or you will likely run into problems. + +# sourceApiVersionMaxMismatch + +The sourceApiVersion in sfdx-project.json doesn't match the max apiVersion of the default target org. As a result, you're not using the latest features available in API version %s. The version mismatch isn't a problem, as long as it's the behavior you actually want. + +# apiVersionMaxMismatch + +The apiVersion doesn't match the max apiVersion of the default target org. As a result, you're not using the latest features available in API version %s. The version mismatch isn't a problem, as long as it's the behavior you actually want. diff --git a/messages/flags.validation.json b/messages/flags.validation.json deleted file mode 100644 index bfdc397d2..000000000 --- a/messages/flags.validation.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "InvalidFlagPath": "The %s command parameter specifies an invalid path: %s\n%s", - "expectedDirectory": "Expected a directory but found a file.", - "expectedFile": "Expected a file but found a directory.", - "notFound": "No such file or directory." -} \ No newline at end of file diff --git a/messages/flags.validation.md b/messages/flags.validation.md new file mode 100644 index 000000000..4993513ca --- /dev/null +++ b/messages/flags.validation.md @@ -0,0 +1,16 @@ +# InvalidFlagPath + +The %s command parameter specifies an invalid path: %s +%s + +# expectedDirectory + +Expected a directory but found a file. + +# expectedFile + +Expected a file but found a directory. + +# notFound + +No such file or directory. diff --git a/messages/ignored_list.json b/messages/ignored_list.json deleted file mode 100644 index 0420461ec..000000000 --- a/messages/ignored_list.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "description": "check your local project package directories for forceignored files", - "examples": ["$ sfdx force:source:ignored", "$ sfdx force:source:ignored --sourcepath force-app"], - "flags": { - "sourcepath": "file or directory of files that the command checks for foreceignored files" - }, - "invalidSourcePath": "File or directory '%s' doesn't exist in your project. Specify one that exists and rerun the command." -} diff --git a/messages/md.cancel.json b/messages/md.cancel.json deleted file mode 100644 index c6c423376..000000000 --- a/messages/md.cancel.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "description": "cancel a metadata deployment \n Use this command to cancel a specified asynchronous metadata deployment. You can also specify a wait time (in minutes) to check for updates to the canceled deploy status.", - "longDescription": "Cancels an asynchronous metadata deployment.", - "flags": { - "wait": "wait time for command to finish in minutes", - "waitLong": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. The default is 33 minutes.", - "jobid": "job ID of the deployment you want to cancel; defaults to your most recent CLI deployment if not specified" - }, - "examples": [ - "Deploy a directory of files to the org", - " $ sfdx force:mdapi:deploy -d ", - "Now cancel this deployment and wait two minutes", - " $ sfdx force:mdapi:deploy:cancel -w 2", - "If you have multiple deployments in progress and want to cancel a specific one, specify the job ID", - " $ sfdx force:mdapi:deploy:cancel -i ", - "Check the status of the cancel job", - " $ sfdx force:mdapi:deploy:report" - ], - "CancelFailed": "The cancel command failed due to: %s" -} diff --git a/messages/md.cancel.md b/messages/md.cancel.md new file mode 100644 index 000000000..b47479fd9 --- /dev/null +++ b/messages/md.cancel.md @@ -0,0 +1,39 @@ +# summary + +Cancel a metadata deployment. + +# description + +Use this command to cancel a specified asynchronous metadata deployment. You can also specify a wait time (in minutes) to check for updates to the canceled deploy status. + +Cancels an asynchronous metadata deployment. + +# flags.wait.summary + +Number of minutes for the command to complete and display results to the terminal window. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# flags.jobid.summary + +Job ID of the deployment you want to cancel; defaults to your most recent CLI deployment. + +# examples + +- Cancel a deployment and wait two minutes: + + <%= config.bin %> <%= command.id %> --wait 2 + +- If you have multiple deployments in progress and want to cancel a specific one, specify the job ID: + + <%= config.bin %> <%= command.id %> --jobid + +# CancelFailed + +The cancel command failed due to: %s. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/md.convert.json b/messages/md.convert.json deleted file mode 100644 index 88c244a68..000000000 --- a/messages/md.convert.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "description": "convert metadata from the Metadata API format into the source format\nConverts metadata retrieved via Metadata API into the source format used in Salesforce DX projects.\n\nTo use Salesforce CLI to work with components that you retrieved via Metadata API, first convert your files from the metadata format to the source format using \"sfdx force:mdapi:convert\".\n\nTo convert files from the source format back to the metadata format, so that you can deploy them using \"sfdx force:mdapi:deploy\", run \"sfdx force:source:convert\".", - "examples": [ - "$ sfdx force:mdapi:convert -r path/to/metadata", - "$ sfdx force:mdapi:convert -r path/to/metadata -d path/to/outputdir" - ], - "flags": { - "rootdir": "the root directory containing the Metadata API–formatted metadata", - "outputdir": "the output directory to store the source–formatted files", - "manifest": "file path to manifest (package.xml) of metadata types to convert.", - "metadatapath": "comma-separated list of metadata file paths to convert", - "metadata": "comma-separated list of metadata component names to convert" - }, - "flagsLong": { - "rootdir": "The root directory that contains the metadata you retrieved using Metadata API.", - "outputdir": "The directory to store your files in after they’re converted to the source format. Can be an absolute or relative path.", - "manifest": [ - "The complete path to the manifest (package.xml) file that specifies the metadata types to convert.", - "If you specify this parameter, don’t specify --metadata or --sourcepath." - ], - "metadatapath": [ - "A comma-separated list of paths to the local metadata files to convert. The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all metadata types in the directory and its sub-directories).", - "If you specify this parameter, don’t specify --manifest or --metadata. If the comma-separated list you’re supplying contains spaces, enclose the entire comma-separated list in one set of double quotes." - ], - "metadata": "A comma-separated list of metadata component names to convert." - } -} diff --git a/messages/md.deploy.json b/messages/md.deploy.json deleted file mode 100644 index a34591c93..000000000 --- a/messages/md.deploy.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "description": "deploy metadata to an org using Metadata API", - "examples": [ - "Return a job ID you can use to check the deploy status:", - "$ sfdx force:mdapi:deploy -d some/path", - "Deploy and poll for 1000 minutes:", - "$ sfdx force:mdapi:deploy -d some/path -w 1000", - "Deploy a ZIP file:", - "$ sfdx force:mdapi:deploy -f stuff.zip", - "Validate a deployment so the ID can be used for a quick deploy:", - "$ sfdx force:mdapi:deploy -d some/path -w 1000 -c --testlevel RunAllTestsInOrg", - "Quick deploy using a previously validated deployment:", - "$ sfdx force:mdapi:deploy -q MyValidatedId" - ], - "flags": { - "checkOnly": "validate deploy but don’t save to the org", - "deployDir": "root of directory tree of files to deploy", - "wait": "wait time for command to finish in minutes. Use -1 to wait indefinitely", - "jobId": "job ID of the deployment to check; required if you’ve never deployed using Salesforce CLI; if not specified, defaults to your most recent CLI deployment", - "testLevel": "deployment testing level", - "runTests": "tests to run if --testlevel RunSpecifiedTests", - "ignoreErrors": "ignore any errors and do not roll back deployment", - "ignoreWarnings": "whether a warning will allow a deployment to complete successfully", - "zipFile": "path to .zip file of metadata to deploy", - "verbose": "verbose output of deploy results", - "validatedDeployRequestId": "request ID of the validated deployment to run a Quick Deploy", - "singlePackage": "Indicates that the zip file points to a directory structure for a single package", - "soapDeploy": "deploy metadata with SOAP API instead of REST API", - "purgeOnDelete": "specify that deleted components in the destructive changes manifest file are immediately eligible for deletion rather than being stored in the Recycle Bin", - "concise": "omit success messages for smaller JSON output", - "junit": "output JUnit test results", - "coverageFormatters": "format of the code coverage results", - "resultsDir": "output directory for code coverage and JUnit results; defaults to the deploy ID" - }, - "flagsLong": { - "checkOnly": "IMPORTANT: Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations.\n\nValidates the deployed metadata and runs all Apex tests, but prevents the deployment from being saved to the org.\nIf you change a field type from Master-Detail to Lookup or vice versa, that change isn’t supported when using the --checkonly parameter to test a deployment (validation). This kind of change isn’t supported for test deployments to avoid the risk of data loss or corruption. If a change that isn’t supported for test deployments is included in a deployment package, the test deployment fails and issues an error.\nIf your deployment package changes a field type from Master-Detail to Lookup or vice versa, you can still validate the changes prior to deploying to Production by performing a full deployment to another test Sandbox. A full deployment includes a validation of the changes as part of the deployment process.\nNote: A Metadata API deployment that includes Master-Detail relationships deletes all detail records in the Recycle Bin in the following cases.\n1. For a deployment with a new Master-Detail field, soft delete (send to the Recycle Bin) all detail records before proceeding to deploy the Master-Detail field, or the deployment fails. During the deployment, detail records are permanently deleted from the Recycle Bin and cannot be recovered.\n2. For a deployment that converts a Lookup field relationship to a Master-Detail relationship, detail records must reference a master record or be soft-deleted (sent to the Recycle Bin) for the deployment to succeed. However, a successful deployment permanently deletes any detail records in the Recycle Bin.", - "deployDir": "The root of the directory tree that contains the files to deploy. The root must contain a valid package.xml file describing the entities in the directory structure. Required to initiate a deployment if you don’t use --zipfile. If you specify both --zipfile and --deploydir, a zip file of the contents of the --deploydir directory is written to the location specified by --zipfile.", - "wait": "The number of minutes to wait for the command to complete. The default is 0 (returns immediately).", - "jobId": "The job ID (id field value for AsyncResult) of the deployment you want to check. The job ID is required if you haven’t previously deployed using Salesforce CLI. If you deploy using Salesforce CLI and don’t specify a job ID, we use the ID of the most recent metadata deployment.", - "testLevel": "Specifies which level of deployment tests to run. Valid values are:\nNoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial orgs. This test level is the default for development environments.\nRunSpecifiedTests—Runs only the tests that you specify in the --runtests option. Code coverage requirements differ from the default coverage requirements when using this test level. Executed tests must comprise a minimum of 75% code coverage for each class and trigger in the deployment package. This coverage is computed for each class and trigger individually and is different than the overall coverage percentage.\nRunLocalTests—All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers.\nRunAllTestsInOrg—All tests in your org are run, including tests of managed packages.\nIf you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see “Running Tests in a Deployment” in the Metadata API Developer Guide.", - "runTests": "Lists the Apex classes containing the deployment tests to run. Use this parameter when you set --testlevel to RunSpecifiedTests.", - "ignoreErrors": "Ignores the deploy errors, and continues with the deploy operation. The default is false. Keep this parameter set to false when deploying to a production org. If set to true, components without errors are deployed, and components with errors are skipped.", - "ignoreWarnings": "If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. When ignoreWarnings is set to false, success is set to false, and the warning is treated like an error.\nThis field is available in API version 18.0 and later. Prior to version 18.0, there was no distinction between warnings and errors. All problems were treated as errors and prevented a successful deployment.", - "zipFile": "The path to the .zip file of metadata files to deploy. You must indicate this option or --deploydir.If you specify both --zipfile and --deploydir, a .zip file of the contents of the deploy directory is created at the path specified for the .zip file.", - "verbose": "Indicates that you want verbose output from the deploy operation.", - "validatedDeployRequestId": "Specifies the ID of a package with recently validated components to run a Quick Deploy. Deploying a validation helps you shorten your deployment time because tests aren’t rerun. If you have a recent successful validation, you can deploy the validated components without running tests. A validation doesn’t save any components in the org. You use a validation only to check the success or failure messages that you would receive with an actual deployment. To validate your components, add the -c | --checkonly flag when you run 'sfdx force:mdapi:deploy'. This flag sets the checkOnly='true' parameter for your deployment. Before deploying a recent validation, ensure that the following requirements are met:\n1. The components have been validated successfully for the target environment within the last 10 days.\n2. As part of the validation, Apex tests in the target org have passed.\n3. Code coverage requirements are met.\n - If all tests in the org or all local tests are run, overall code coverage is at least 75%, and Apex triggers have some coverage.\n - If specific tests are run with the RunSpecifiedTests test level, each class and trigger that was deployed is covered by at least 75% individually.", - "singlePackage": "Indicates that the specified .zip file points to a directory structure for a single package. By default, the CLI assumes the directory is structured for a set of packages.", - "soapDeploy": "Deploy metadata with SOAP API instead of the default REST API. Because SOAP API has a lower .ZIP file size limit (400 MB uncompressed, 39 MB compressed), Salesforce recommends REST API deployment. This flag provides backwards compatibility with API version 50.0 and earlier when deploy used SOAP API by default." - }, - "noRestDeploy": "REST deploy is not available for this org. This feature is currently for internal Salesforce use only.", - "deployFailed": "The metadata deploy operation failed. %s", - "asyncDeployQueued": "Deploy has been queued.", - "asyncDeployCancel": "Run sfdx force:mdapi:deploy:cancel -i %s -u %s to cancel the deploy.", - "asyncDeployReport": "Run sfdx force:mdapi:deploy:report -i %s -u %s to get the latest status.", - "asyncCoverageJunitWarning": "You requested an async deploy with code coverage or JUnit results. The reports will be available when the deploy completes." -} diff --git a/messages/md.deploy.md b/messages/md.deploy.md new file mode 100644 index 000000000..9881dce9f --- /dev/null +++ b/messages/md.deploy.md @@ -0,0 +1,200 @@ +# summary + +Deploy metadata to an org using Metadata API. + +# examples + +- Return a job ID you can use to check the deploy status: + + <%= config.bin %> <%= command.id %> --deploydir some/path + +- Deploy and poll for 1000 minutes: + + <%= config.bin %> <%= command.id %> --deploydir some/path --wait 1000 + +- Deploy a ZIP file: + + <%= config.bin %> <%= command.id %> --zipfile stuff.zip + +- Validate a deployment so the ID can be used for a quick deploy: + + <%= config.bin %> <%= command.id %> --deploydir some/path --wait 1000 --checkonly --testlevel RunAllTestsInOrg + +- Quick deploy using a previously validated deployment: + + <%= config.bin %> <%= command.id %> --validateddeployrequestid MyValidatedId + +# flags.checkOnly.summary + +Validates the deployed metadata and runs all Apex tests, but prevents the deployment from being saved to the org. + +# flags.deployDir.summary + +Root of directory tree that contains the files you want to deploy. + +# flags.wait.summary + +Number of minutes to wait for the command to finish; specify -1 to wait indefinitely. + +# flags.jobId.summary + +Job ID of the deployment to check. + +# flags.testLevel.summary + +Level of deployment tests to run. + +# flags.runTests.summary + +Apex test classes to run if --testlevel is RunSpecifiedTests. + +# flags.ignoreErrors.summary + +Ignore any errors and don't roll back the deployment. + +# flags.ignoreWarnings.summary + +Ignore any warnings and don't roll back the deployment. + +# flags.zipFile.summary + +Path to .zip file of metadata to deploy. + +# flags.verbose.summary + +Display verbose output of the deploy results. + +# flags.validatedDeployRequestId.summary + +Request ID of the validated deployment to run a Quick Deploy. + +# flags.singlePackage.summary + +Indicates that the zip file points to a directory structure for a single package. + +# flags.soapDeploy.summary + +Deploy metadata with SOAP API instead of REST API. + +# flags.purgeOnDelete.summary + +Specify that deleted components in the destructive changes manifest file are immediately eligible for deletion rather than being stored in the Recycle Bin. + +# flags.concise.summary + +Omit success messages for smaller JSON output. + +# flags.junit.summary + +Output JUnit test results. + +# flags.coverageFormatters.summary + +Format of the code coverage results. + +# flags.resultsDir.summary + +Output directory for code coverage and JUnit results; defaults to the deploy ID. + +# flags.checkOnly.description + +IMPORTANT: Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations. + +If you change a field type from Master-Detail to Lookup or vice versa, that change isn’t supported when using the --checkonly parameter to test a deployment (validation). This kind of change isn’t supported for test deployments to avoid the risk of data loss or corruption. If a change that isn’t supported for test deployments is included in a deployment package, the test deployment fails and issues an error. + +If your deployment package changes a field type from Master-Detail to Lookup or vice versa, you can still validate the changes prior to deploying to Production by performing a full deployment to another test Sandbox. A full deployment includes a validation of the changes as part of the deployment process. + +Note: A Metadata API deployment that includes Master-Detail relationships deletes all detail records in the Recycle Bin in the following cases. + + 1. For a deployment with a new Master-Detail field, soft delete (send to the Recycle Bin) all detail records before proceeding to deploy the Master-Detail field, or the deployment fails. During the deployment, detail records are permanently deleted from the Recycle Bin and cannot be recovered. + 2. For a deployment that converts a Lookup field relationship to a Master-Detail relationship, detail records must reference a master record or be soft-deleted (sent to the Recycle Bin) for the deployment to succeed. However, a successful deployment permanently deletes any detail records in the Recycle Bin. + +# flags.deployDir.description + +The root must contain a valid package.xml file describing the entities in the directory structure. Required to initiate a deployment if you don’t use --zipfile. If you specify both --zipfile and --deploydir, a zip file of the contents of the --deploydir directory is written to the location specified by --zipfile. + +# flags.wait.description + +The default is 0 (returns immediately). + +# flags.jobId.description + +The job ID is required if you haven’t previously deployed using Salesforce CLI. If you deploy using Salesforce CLI and don’t specify a job ID, we use the ID of the most recent metadata deployment. + +# flags.testLevel.description + +Valid values are: + + * NoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial orgs. This test level is the default for development environments. + * RunSpecifiedTests—Runs only the tests that you specify in the --runtests option. Code coverage requirements differ from the default coverage requirements when using this test level. Executed tests must comprise a minimum of 75% code coverage for each class and trigger in the deployment package. This coverage is computed for each class and trigger individually and is different than the overall coverage percentage. + * RunLocalTests—All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers. + * RunAllTestsInOrg—All tests in your org are run, including tests of managed packages. + +If you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see “Running Tests in a Deployment” in the Metadata API Developer Guide. + +# flags.ignoreErrors.description + +The default is false. Keep this parameter set to false when deploying to a production org. If set to true, components without errors are deployed, and components with errors are skipped. + +# flags.ignoreWarnings.description + +If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. When ignoreWarnings is set to false, success is set to false, and the warning is treated like an error. +This field is available in API version 18.0 and later. Prior to version 18.0, there was no distinction between warnings and errors. All problems were treated as errors and prevented a successful deployment. + +# flags.zipFile.description + +You must indicate this option or --deploydir. If you specify both --zipfile and --deploydir, a .zip file of the contents of the deploy directory is created at the path specified for the .zip file. + +# flags.verbose.description + +Indicates that you want verbose output from the deploy operation. + +# flags.validatedDeployRequestId.description + +Deploying a validation helps you shorten your deployment time because tests aren’t rerun. If you have a recent successful validation, you can deploy the validated components without running tests. A validation doesn’t save any components in the org. You use a validation only to check the success or failure messages that you would receive with an actual deployment. To validate your components, add the -c | --checkonly flag when you run 'force mdapi deploy'. This flag sets the checkOnly='true' parameter for your deployment. Before deploying a recent validation, ensure that the following requirements are met: + + 1. The components have been validated successfully for the target environment within the last 10 days. + 2. As part of the validation, Apex tests in the target org have passed. + 3. Code coverage requirements are met. + - If all tests in the org or all local tests are run, overall code coverage is at least 75%, and Apex triggers have some coverage. + - If specific tests are run with the RunSpecifiedTests test level, each class and trigger that was deployed is covered by at least 75% individually. + +# flags.singlePackage.description + +By default, the CLI assumes the directory is structured for a set of packages. + +# flags.soapDeploy.description + +Because SOAP API has a lower .ZIP file size limit (400 MB uncompressed, 39 MB compressed), Salesforce recommends REST API deployment. This flag provides backwards compatibility with API version 50.0 and earlier when deploy used SOAP API by default. + +# noRestDeploy + +REST deploy is not available for this org. This feature is currently for internal Salesforce use only. + +# deployFailed + +The metadata deploy operation failed. %s + +# asyncDeployQueued + +Deploy has been queued. + +# asyncDeployCancel + +Run sfdx force:mdapi:deploy:cancel -i %s -u %s to cancel the deploy. + +# asyncDeployReport + +Run sfdx force:mdapi:deploy:report -i %s -u %s to get the latest status. + +# deployCanceled + +The deployment has been canceled by %s. + +# asyncCoverageJunitWarning + +You requested an async deploy with code coverage or JUnit results. The reports will be available when the deploy completes. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/md.deployreport.json b/messages/md.deployreport.json deleted file mode 100644 index d2b6a9827..000000000 --- a/messages/md.deployreport.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "check the status of a metadata deployment", - "mdDeployReportCommandCliHelp": "Specify the job ID for the deploy you want to check. The job ID is returned by the force:mdapi:deploy command when run without the --wait parameter. You can also specify a wait time (minutes) to check for updates to the deploy status.", - "examples": [ - "Check the status of the most recent deployment", - "$ sfdx force:mdapi:deploy:report", - "Check the status of a deploy with job ID 1234 and wait for 10 minutes for the result:", - "$ sfdx force:mdapi:deploy:report -i 1234 -w 10" - ], - "flags": { - "verbose": "verbose output of deploy results", - "jobId": "job ID of the deployment to check; required if you’ve never deployed using Salesforce CLI; if not specified, defaults to your most recent CLI deployment", - "wait": "wait time for command to finish in minutes. Use -1 to poll indefinitely", - "concise": "omit success messages for smaller JSON output", - "junit": "output JUnit test results", - "coverageFormatters": "format of the code coverage results", - "resultsDir": "output directory for code coverage and JUnit results; defaults to the deploy ID" - }, - "flagsLong": { - "jobId": "The job ID (id field value for AsyncResult) of the deployment you want to check. The job ID is required if you haven’t previously deployed using Salesforce CLI. If you deploy using Salesforce CLI and don’t specify a job ID, we use the ID of the most recent metadata deployment.", - "verbose": "Indicates that you want verbose output for deploy results.", - "wait": "The number of minutes to wait for the command to complete. The default is –1 (no limit)." - }, - "usernameOutput": "Using specified username %s" -} diff --git a/messages/md.deployreport.md b/messages/md.deployreport.md new file mode 100644 index 000000000..b95258d7f --- /dev/null +++ b/messages/md.deployreport.md @@ -0,0 +1,57 @@ +# summary + +Check the status of a metadata deployment. + +# description + +Specify the job ID for the deploy you want to check. The job ID is returned by the "force mdapi deploy" command when run without the --wait parameter. You can also specify a wait time (minutes) to check for updates to the deploy status. + +# examples + +- Check the status of the most recent deployment + + <%= config.bin %> <%= command.id %> + +- Check the status of a deploy with job ID 1234 and wait for 10 minutes for the result: + + <%= config.bin %> <%= command.id %> --jobid 1234 --wait 10 + +# flags.verbose.summary + +Verbose output of deploy results. + +# flags.jobId.summary + +Job ID of the deployment to check; required if you’ve never deployed using Salesforce CLI; defaults to your most recent CLI deployment. + +# flags.wait.summary + +Number of minutes to wait for the command to finish; use -1 to poll indefinitely. + +# flags.concise.summary + +Omit success messages for smaller JSON output. + +# flags.junit.summary + +Output JUnit test results. + +# flags.coverageFormatters.summary + +Format of the code coverage results. + +# flags.resultsDir.summary + +Output directory for code coverage and JUnit results; defaults to the deploy ID. + +# flags.jobId.description + +The job ID (id field value for AsyncResult) of the deployment you want to check. The job ID is required if you haven’t previously deployed using Salesforce CLI. If you deploy using Salesforce CLI and don’t specify a job ID, we use the ID of the most recent metadata deployment. + +# usernameOutput + +Using specified username %s. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/md.retrieve.json b/messages/md.retrieve.json deleted file mode 100644 index 80c383fbb..000000000 --- a/messages/md.retrieve.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "retrieveCmd": { - "description": "retrieve metadata from an org using Metadata API\nUses Metadata API to retrieve a .zip of XML files that represent metadata from the targeted org. The default target username is the admin user for the default scratch org. You can retrieve and deploy up to 10,000 files or 400 MB (39 MB compressed) at one time.", - "examples": [ - "Retrieve metadata in the default project directory into the target directory:", - "$ sfdx force:mdapi:retrieve -r path/to/retrieve/dir", - "Retrieve metadata defined in the specified manifest into the target directory:", - "$ sfdx force:mdapi:retrieve -r path/to/retrieve/dir -k package.xml", - "Retrieve metadata defined by the specified directory, name the retrieved zipfile and extract all contents", - "$ sfdx force:mdapi:retrieve -d path/to/apexClasses -r path/to/retrieve/dir --unzip --zipfilename apexClasses.zip", - "Enqueue a retrieve request but do not wait for the metadata to be retrieved:", - "$ sfdx force:mdapi:retrieve -r path/to/retrieve/dir --wait 0" - ] - }, - "reportCmd": { - "description": "check the status of a metadata retrieval\nSpecify the job ID and a target directory for the retrieve you want to check. You can also specify a wait time (minutes) to check for updates to the retrieve status. If the retrieve was successful, the resulting zip file will be saved to the location passed in with the retrieve target parameter.", - "examples": [ - "Poll until the metadata is retrieved (or timeout is reached) using data from the last force:mdapi:retrieve command:", - " sfdx force:mdapi:retrieve:report", - "Report the current status of the last retrieve command. If the retrieve is complete the zip file of metadata is written to the target directoy:", - " sfdx force:mdapi:retrieve:report -r path/to/retrieve/dir -w 0", - "Poll until the metadata is retrieved (or timeout is reached) using the provided RetrieveID, naming the zip file and extracting all contents:", - " sfdx force:mdapi:retrieve:report -i retrieveId -r path/to/retrieve/dir --unzip --zipfilename apexClasses.zip" - ] - }, - "flags": { - "retrievetargetdir": "directory root for the retrieved files", - "unpackaged": "file path of manifest of components to retrieve", - "sourcedir": "source dir to use instead of the default package dir in sfdx-project.json", - "packagenames": "a comma-separated list of packages to retrieve", - "singlepackage": "indicates that the zip file points to a directory structure for a single package", - "zipfilename": "file name to use for the retrieved zip file", - "unzip": "extract all files from the retrieved zip file", - "wait": "wait time for command to finish in minutes", - "apiversion": "target API version for the retrieve", - "verbose": "verbose output of retrieve result", - "jobid": "job ID of the retrieve you want to check; defaults to your most recent CLI retrieval if not specified" - }, - "flagsLong": { - "retrievetargetdir": "The root of the directory structure where the retrieved .zip or metadata files are put.", - "unpackaged": "The complete path for the manifest file that specifies the components to retrieve.", - "sourcedir": "The source directory to use instead of the default package directory specified in sfdx-project.json", - "packagenames": "A comma-separated list of package names to retrieve.", - "singlepackage": "Indicates that the specified .zip file points to a directory structure for a single package. By default, the CLI assumes the directory is structured for a set of packages.", - "zipfilename": "The file name to use for the retrieved zip file.", - "unzip": "Extract all files from the retrieved zip file.", - "wait": "The number of minutes to wait for the command to complete.", - "apiversion": "Use to override the default, which is the latest version supported by your CLI plug-in, with the version in your package.xml file.", - "verbose": "Indicates that you want verbose output from the retrieve operation.", - "jobid": "The job ID (asyncId) of the retrieve you want to check. If not specified, the default value is the ID of the most recent metadata retrieval you ran using Salesforce CLI. You must specify a --retrievetargetdir. Use with --wait to resume waiting." - }, - "InvalidPackageNames": "You specified [%s]. Try again and specify only one package when using --singlepackage.", - "MissingRetrieveId": "The jobid command parameter was not provided, neither directly nor from a previous retrieval.", - "checkStatus": "To check the status of this retrieve, run \"sfdx force:mdapi:retrieve:report %s\".\nIf the retrieve request has completed, the retrieved metadata zip file will be written to the retrieve target dir." -} diff --git a/messages/md.retrieve.md b/messages/md.retrieve.md new file mode 100644 index 000000000..05dd79bec --- /dev/null +++ b/messages/md.retrieve.md @@ -0,0 +1,120 @@ +# retrieve.summary + +Retrieve metadata from an org using Metadata API. + +# retrieve.description + +This command uses Metadata API to retrieve a .zip of XML files that represent metadata from the targeted org. You can retrieve and deploy up to 10,000 files or 400 MB (39 MB compressed) at one time. + +# retrieve.examples + +- Retrieve metadata in the default project directory into the target directory: + + <%= config.bin %> <%= command.id %> --retrievetargetdir path/to/retrieve/dir + +- Retrieve metadata defined in the specified manifest into the target directory: + + <%= config.bin %> <%= command.id %> --retrievetargetdir path/to/retrieve/dir --unpackaged package.xml + +- Retrieve metadata defined by the specified directory, name the retrieved zipfile and extract all contents + + <%= config.bin %> <%= command.id %> --sourcedir path/to/apexClasses --retrievetargetdir path/to/retrieve/dir --unzip --zipfilename apexClasses.zip + +- Enqueue a retrieve request but do not wait for the metadata to be retrieved: + + <%= config.bin %> <%= command.id %> --retrievetargetdir path/to/retrieve/dir --wait 0 + +# report.summary + +Check the status of a metadata retrieval. + +# report.description + +Specify the job ID and a target directory for the retrieve you want to check. You can also specify a wait time (minutes) to check for updates to the retrieve status. If the retrieve was successful, the resulting zip file will be saved to the location passed in with the retrieve target parameter. + +# report.examples + +- Poll until the metadata is retrieved (or timeout is reached) using data from the last force:mdapi:retrieve command: + + <%= config.bin %> <%= command.id %> + +- Report the current status of the last retrieve command. If the retrieve is complete the zip file of metadata is written to the target directoy: + + <%= config.bin %> <%= command.id %> --retrievetargetdir path/to/retrieve/dir --wait 0 + +- Poll until the metadata is retrieved (or timeout is reached) using the provided RetrieveID, naming the zip file and extracting all contents: + + <%= config.bin %> <%= command.id %> -i retrieveId --retrievetargetdir path/to/retrieve/dir --unzip --zipfilename apexClasses.zip + +# flags.retrievetargetdir.summary + +Root of the directory structure where the retrieved .zip or metadata files are retrieved. + +# flags.unpackaged.summary + +Complete path for the manifest file that specifies the components to retrieve. + +# flags.sourcedir.summary + +Source directory to use instead of the default package directory specified in sfdx-project.json. + +# flags.packagenames.summary + +Comma-separated list of packages to retrieve. + +# flags.singlepackage.summary + +Specify that the zip file points to a directory structure for a single package. + +# flags.zipfilename.summary + +File name to use for the retrieved zip file. + +# flags.unzip.summary + +Extract all files from the retrieved zip file. + +# flags.wait.summary + +Number of minutes to wait for the command to complete. + +# flags.apiversion.summary + +Target API version for the retrieve. + +# flags.verbose.summary + +Display verbose output of retrieve result. + +# flags.jobid.summary + +Job ID of the retrieve you want to check; defaults to your most recent CLI retrieval. + +# flags.singlepackage.description + +By default, the CLI assumes the directory is structured for a set of packages. + +# flags.apiversion.description + +Use to override the default, which is the latest version supported by your CLI plug-in, with the version in your package.xml file. + +# flags.jobid.description + +You must specify a --retrievetargetdir. Use with --wait to resume waiting. + +# InvalidPackageNames + +You specified [%s]. Try again and specify only one package when using --singlepackage. + +# MissingRetrieveId + +The jobid command parameter was not provided, neither directly nor from a previous retrieval. + +# checkStatus + +To check the status of this retrieve, run "sfdx force:mdapi:retrieve:report %s". +If the retrieve request has completed, the retrieved metadata zip file will be written to the retrieve target dir. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/pull.json b/messages/pull.json deleted file mode 100644 index b307365ee..000000000 --- a/messages/pull.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "pull source from the scratch org to the project", - "descriptionLong": "Pulls changed source from the scratch org to your project to keep them in sync.", - "help": "If the command detects a conflict, it displays the conflicts but does not complete the process. After reviewing the conflict, rerun the command with the --forceoverwrite parameter.", - "flags": { - "forceoverwrite": "ignore conflict warnings and overwrite changes to the project", - "forceoverwriteLong": "Runs the pull command even if conflicts exist. Changes in the scratch org overwrite changes in the project.", - "waitLong": "The number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. The default is 33 minutes." - }, - "NonScratchOrgPull": "We can\"t retrieve your changes. \"force:source:pull\" is only available for orgs that have source tracking enabled. Use \"force:source:retrieve\" or \"force:mdapi:retrieve\" instead.", - "sourceConflictDetected": "Source conflict(s) detected.", - "pull": "Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time.", - "retrievedSourceHeader": "Retrieved Source", - "NoResultsFound": "No results found", - "retrievedSourceWarningsHeader": "Retrieved Source Warnings", - "retrieveTimeout": "Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time." -} diff --git a/messages/pull.md b/messages/pull.md new file mode 100644 index 000000000..5329fba24 --- /dev/null +++ b/messages/pull.md @@ -0,0 +1,65 @@ +# summary + +Pull changed source from the org to your project to keep them in sync. + +# description + +If the command detects a conflict, it displays the conflicts but does not complete the process. After reviewing the conflict, rerun the command with the --forceoverwrite parameter. + +# examples + +- Pull source from your default org: + + <%= config.bin %> <%= command.id %> + +- Pull source from the org with alias "myscratch"; ignore any conflicts and overwrite the local project files with org changes; wait for only 5 minutes: + + <%= config.bin %> <%= command.id %> --target-org myscratch --wait 5 --forceoverwrite + +# flags.verbose.summary + +Display additional details about the command results. + +# flags.forceoverwrite.summary + +Ignore conflict warnings; changes in the org overwrite changes in the project. + +# flags.wait.summary + +Number of minutes to wait for the command to complete and display results to the terminal window. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# NonScratchOrgPull + +We can"t retrieve your changes. "force source pull" is only available for orgs that have source tracking enabled. Use "force source retrieve" or "force mdapi retrieve" instead. + +# sourceConflictDetected + +Source conflict(s) detected. + +# pull + +Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time. + +# retrievedSourceHeader + +Retrieved Source + +# NoResultsFound + +No results found + +# retrievedSourceWarningsHeader + +Retrieved Source Warnings + +# retrieveTimeout + +Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/push.json b/messages/push.json deleted file mode 100644 index 990db2b13..000000000 --- a/messages/push.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "push source to a scratch org from the project", - "descriptionLong": "Pushes changed source from your project to a scratch org to keep them in sync.", - "help": "If the command detects a conflict, it displays the conflicts but does not complete the process. After reviewing the conflict, rerun the command with the --forceoverwrite parameter.", - "flags": { - "waitLong": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. The default is 33 minutes.", - "forceoverwrite": "ignore conflict warnings and overwrite changes to scratch org", - "forceoverwriteLong": "Runs the push command even if conflicts exist. Changes in the project overwrite changes in the scratch org.", - "replacetokens": "replace tokens in source files prior to deployment", - "replacetokensLong": "Replaces tokens in source files prior to deployment.", - "ignorewarnings": "deploy changes even if warnings are generated", - "ignorewarningsLong": "Completes the deployment even if warnings are generated.", - "quiet": "minimize json and sdtout output on success" - }, - "sourcepushFailed": "Push failed. %s", - "sequentialFail": "Check the order of your dependencies and ensure all metadata is included." -} diff --git a/messages/push.md b/messages/push.md new file mode 100644 index 000000000..df1ab315d --- /dev/null +++ b/messages/push.md @@ -0,0 +1,53 @@ +# summary + +Push changed source from your project to an org to keep them in sync. + +# description + +If the command detects a conflict, it displays the conflicts but does not complete the process. After reviewing the conflict, rerun the command with the --forceoverwrite parameter. + +# examples + +- Push source to your default org: + + <%= config.bin %> <%= command.id %> + +- Push source to the org with alias "myscratch"; ignore any conflicts and overwrite with org with the local project changes; wait for only 5 minutes: + + <%= config.bin %> <%= command.id %> --target-org myscratch --wait 5 --forceoverwrite + +# flags.wait.summary + +Number of minutes to wait for the command to complete and display results to the terminal window. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# flags.forceoverwrite.summary + +Ignore conflict warnings and push source anyway; changes in the project overwrite changes in the org. + +# flags.replacetokens.summary + +Replace tokens in source files prior to deployment. + +# flags.ignorewarnings.summary + +Deploy changes even if warnings are generated. + +# flags.quiet.summary + +Minimize JSON and sdtout output on success. + +# sourcepushFailed + +Push failed. %s + +# sequentialFail + +Check the order of your dependencies and ensure all metadata is included. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/report.json b/messages/report.json deleted file mode 100644 index 48b7d65cd..000000000 --- a/messages/report.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "description": "check the status of a metadata deployment \nSpecify the job ID for the deploy you want to check. You can also specify a wait time (minutes) to check for updates to the deploy status.", - "examples": [ - "Deploy a directory of files to the org", - " $ sfdx force:source:deploy -d ", - "Now cancel this deployment and wait two minutes", - " $ sfdx force:source:deploy:cancel -w 2", - "If you have multiple deployments in progress and want to cancel a specific one, specify the job ID", - " $ sfdx force:source:deploy:cancel -i ", - "Check the status of the cancel job", - " $ sfdx force:source:deploy:report" - ], - "flags": { - "jobid": "job ID of the deployment you want to check; defaults to your most recent CLI deployment if not specified", - "wait": "wait time for command to finish in minutes", - "verbose": "verbose output of deploy result", - "junit": "output JUnit test results", - "coverageFormatters": "format of the code coverage results", - "resultsDir": "output directory for code coverage and JUnit results; defaults to the deploy ID" - }, - "flagsLong": { - "wait": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you. ", - "jobid": "The job ID (asyncId) of the deployment you want to check. If not specified, the default value is the ID of the most recent metadata deployment you ran using Salesforce CLI. Use with -w to resume waiting." - }, - "mdapiDeployFailed": "The metadata deploy operation failed." -} diff --git a/messages/report.md b/messages/report.md new file mode 100644 index 000000000..ebbdb01fa --- /dev/null +++ b/messages/report.md @@ -0,0 +1,53 @@ +# summary + +Check the status of a metadata deployment. + +# description + +Specify the job ID for the deploy you want to check. You can also specify a wait time (minutes) to check for updates to the deploy status. + +# examples + +- Check the status of the most recent deployment on your default org: + + <%= config.bin %> <%= command.id %> + +- Check the status using the job ID; output JUnit test results and format code coverage results in the specified format: + + <%= config.bin %> <%= command.id %> --jobid --junit --coverageformatters cobertura + +# flags.jobid.summary + +Job ID of the deployment you want to check; defaults to your most recent CLI deployment. + +# flags.wait.summary + +Number of minutes to wait for the command to complete and display results to the terminal window. + +# flags.verbose.summary + +Verbose output of deploy result. + +# flags.junit.summary + +Output JUnit test results. + +# flags.coverageFormatters.summary + +Format of the code coverage results. + +# flags.resultsDir.summary + +Output directory for code coverage and JUnit results; defaults to the deploy ID. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# mdapiDeployFailed + +The metadata deploy operation failed. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/retrieve.json b/messages/retrieve.json deleted file mode 100644 index 54bd28290..000000000 --- a/messages/retrieve.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "description": "retrieve source from an org \nUse this command to retrieve source (metadata that’s in source format) from an org.\nTo take advantage of change tracking with scratch orgs, use \"sfdx force:source:pull\".\nTo retrieve metadata that’s in metadata format, use \"sfdx force:mdapi:retrieve\".\n\nThe source you retrieve overwrites the corresponding source files in your local project. This command does not attempt to merge the source from your org with your local source files.\n\nIf the comma-separated list you’re supplying contains spaces, enclose the entire comma-separated list in one set of double quotes. On Windows, if the list contains commas, also enclose it in one set of double quotes.", - "examples": [ - "To retrieve the source files in a directory:\n $ sfdx force:source:retrieve -p path/to/source", - "To retrieve a specific Apex class and the objects whose source is in a directory:\n $ sfdx force:source:retrieve -p \"path/to/apex/classes/MyClass.cls,path/to/source/objects\"", - "To retrieve source files in a comma-separated list that contains spaces:\n $ sfdx force:source:retrieve -p \"path/to/objects/MyCustomObject/fields/MyField.field-meta.xml, path/to/apex/classes\"", - "To retrieve all Apex classes:\n $ sfdx force:source:retrieve -m ApexClass", - "To retrieve a specific Apex class:\n $ sfdx force:source:retrieve -m ApexClass:MyApexClass", - "To retrieve a specific Apex class and update source tracking files:\n $ sfdx force:source:retrieve -m ApexClass:MyApexClass -t", - "To retrieve all custom objects and Apex classes:\n $ sfdx force:source:retrieve -m \"CustomObject,ApexClass\"", - "To retrieve all Apex classes and two specific profiles (one of which has a space in its name):\n $ sfdx force:source:retrieve -m \"ApexClass, Profile:My Profile, Profile: AnotherProfile\"", - "To retrieve all metadata components listed in a manifest:\n $ sfdx force:source:retrieve -x path/to/package.xml", - "To retrieve metadata from a package or multiple packages:\n $ sfdx force:source:retrieve -n MyPackageName\n $ sfdx force:source:retrieve -n \"Package1, PackageName With Spaces, Package3\"", - "To retrieve all metadata from a package and specific components that aren’t in the package, specify both -n | --packagenames and one other scoping parameter:\n $ sfdx force:source:retrieve -n MyPackageName -p path/to/apex/classes\n $ sfdx force:source:retrieve -n MyPackageName -m ApexClass:MyApexClass\n $ sfdx force:source:retrieve -n MyPackageName -x path/to/package.xml", - "To retrieve source files to a given directory instead of the default package directory specified in sfdx-project.json:\n $ sfdx force:source:retrieve -m \"StandardValueSet:TaskStatus\" -r path/to/unpackaged" - ], - "flags": { - "retrievetargetdir": "directory root for the retrieved source files", - "sourcePath": "comma-separated list of source file paths to retrieve", - "wait": "wait time for command to finish in minutes", - "manifest": "file path for manifest (package.xml) of components to retrieve", - "metadata": "comma-separated list of metadata component names", - "packagename": "a comma-separated list of packages to retrieve", - "tracksource": "if the retrieve succeeds, update source tracking information; doesn't delete local files that were deleted in the org", - "verbose": "verbose output of retrieve result", - "forceoverwrite": "ignore conflict warnings and overwrite changes to the project" - }, - "flagsLong": { - "retrievetargetdir": [ - "The root of the directory structure into which the source files are retrieved.", - "If the target directory matches one of the package directories in your sfdx-project.json file, the command fails.", - "Running the command multiple times with the same target adds new files and overwrites existing files." - ], - "wait": "Number of minutes to wait for the command to complete and display results to the terminal window. If the command continues to run after the wait period, the CLI returns control of the terminal window to you.", - "manifest": [ - "The complete path for the manifest (package.xml) file that specifies the components to retrieve.", - "If you specify this parameter, don’t specify --metadata or --sourcepath." - ], - "metadata": [ - "A comma-separated list of names of metadata components to retrieve from the org.", - "If you specify this parameter, don’t specify --manifest or --sourcepath." - ], - "sourcePath": [ - "A comma-separated list of file paths for source to retrieve from the org. The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all source files in the directory and its sub-directories).", - "If you specify this parameter, don’t specify --manifest or --metadata." - ] - }, - "SourceRetrieveError": "Could not retrieve files in the sourcepath%s", - "retrieveTimeout": "Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time.", - "retrievedSourceHeader": "Retrieved Source", - "retrievedSourceWarningsHeader": "Retrieved Source Warnings", - "fullNameTableColumn": "FULL NAME", - "typeTableColumn": "TYPE", - "workspacePathTableColumn": "PROJECT PATH", - "NoResultsFound": "No results found", - "metadataNotFoundWarning": "WARNING: The following metadata isn’t in your org. If it’s not new, someone deleted it from the org.", - "columnNumberColumn": "COLUMN NUMBER", - "lineNumberColumn": "LINE NUMBER", - "errorColumn": "PROBLEM", - "nothingToRetrieve": "Specify a source path, manifest, metadata, or package names to retrieve.", - "wantsToRetrieveCustomFields": "Because you're retrieving one or more CustomFields, we're also retrieving the CustomObject to which it's associated.", - "retrieveWontDelete": "You currently have files deleted in your org. The retrieve command will NOT delete them from your local project", - "retrieveTargetDirOverlapsPackage": "The retrieve target directory [%s] overlaps one of your package directories. Specify a different retrieve target directory and try again.", - "apiVersionMsgDetailed": "%s v%s metadata from %s using the v%s SOAP API" -} diff --git a/messages/retrieve.md b/messages/retrieve.md new file mode 100644 index 000000000..f429be8eb --- /dev/null +++ b/messages/retrieve.md @@ -0,0 +1,196 @@ +# summary + +Retrieve source from an org. + +# description + +Use this command to retrieve source (metadata that’s in source format) from an org. To take advantage of change tracking with scratch orgs, use "force source pull". To retrieve metadata that’s in metadata format, use "force mdapi retrieve". + +The source you retrieve overwrites the corresponding source files in your local project. This command does not attempt to merge the source from your org with your local source files. + +If the comma-separated list you’re supplying contains spaces, enclose the entire comma-separated list in one set of double quotes. On Windows, if the list contains commas, also enclose it in one set of double quotes. + +# examples + +- Retrieve the source files in a directory from your default org: + + <%= config.bin %> <%= command.id %> --sourcepath path/to/source + +- Retrieve a specific Apex class and the objects whose source is in a directory from an org with alias "myscratch": + + <%= config.bin %> <%= command.id %> --sourcepath "path/to/apex/classes/MyClass.cls,path/to/source/objects" --target-org myscratch + +- Retrieve source files in a comma-separated list that contains spaces: + + <%= config.bin %> <%= command.id %> --sourcepath "path/to/objects/MyCustomObject/fields/MyField.field-meta.xml, path/to/apex/classes" + +- Retrieve all Apex classes: + + <%= config.bin %> <%= command.id %> --metadata ApexClass + +- Retrieve a specific Apex class: + + <%= config.bin %> <%= command.id %> --metadata ApexClass:MyApexClass + +- Retrieve a specific Apex class and update source tracking files: + + <%= config.bin %> <%= command.id %> --metadata ApexClass:MyApexClass --tracksource + +- Retrieve all custom objects and Apex classes: + + <%= config.bin %> <%= command.id %> --metadata "CustomObject,ApexClass" + +- Retrieve all Apex classes and two specific profiles (one of which has a space in its name): + + <%= config.bin %> <%= command.id %> --metadata "ApexClass, Profile:My Profile, Profile: AnotherProfile" + +- Retrieve all metadata components listed in a manifest: + + <%= config.bin %> <%= command.id %> --manifest path/to/package.xml + +- Retrieve metadata from a package or multiple packages: + + <%= config.bin %> <%= command.id %> --packagenames MyPackageName + <%= config.bin %> <%= command.id %> --packagenames "Package1, PackageName With Spaces, Package3" + +- Retrieve all metadata from a package and specific components that aren’t in the package, specify both -n | --packagenames and one other scoping parameter: + + <%= config.bin %> <%= command.id %> --packagenames MyPackageName --sourcepath path/to/apex/classes + <%= config.bin %> <%= command.id %> --packagenames MyPackageName --metadata ApexClass:MyApexClass + <%= config.bin %> <%= command.id %> --packagenames MyPackageName --manifest path/to/package.xml + +- Retrieve source files to a given directory instead of the default package directory specified in sfdx-project.json: + + <%= config.bin %> <%= command.id %> --metadata "StandardValueSet:TaskStatus" --retrievetargetdir path/to/unpackaged + +# flags.retrievetargetdir.summary + +Root of the directory structure into which the source files are retrieved. + +# flags.sourcePath.summary + +Comma-separated list of file paths for source to retrieve from the org. + +# flags.wait.summary + +Number of minutes to wait for the command to complete and display results to the terminal window. + +# flags.manifest.summary + +Complete path for the manifest (package.xml) file that specifies the components to retrieve. + +# flags.metadata.summary + +Comma-separated list of names of metadata components to retrieve from the org. + +# flags.packagename.summary + +Comma-separated list of packages to retrieve. + +# flags.tracksource.summary + +If the retrieve succeeds, update source tracking information; doesn't delete local files that were deleted in the org. + +# flags.verbose.summary + +Verbose output of retrieve result. + +# flags.forceoverwrite.summary + +Ignore conflict warnings and overwrite changes to the project. + +# flags.retrievetargetdir.description + +If the target directory matches one of the package directories in your sfdx-project.json file, the command fails. + +Running the command multiple times with the same target adds new files and overwrites existing files. + +# flags.wait.description + +If the command continues to run after the wait period, the CLI returns control of the terminal window to you. + +# flags.manifest.description + +If you specify this parameter, don’t specify --metadata or --sourcepath. + +# flags.metadata.description + +If you specify this parameter, don’t specify --manifest or --sourcepath. + +# flags.sourcePath.description + +The supplied paths can be to a single file (in which case the operation is applied to only one file) or to a folder (in which case the operation is applied to all source files in the directory and its sub-directories). + +If you specify this parameter, don’t specify --manifest or --metadata. + +# SourceRetrieveError + +Could not retrieve files in the sourcepath%s + +# retrieveTimeout + +Your retrieve request did not complete within the specified wait time [%s minutes]. Try again with a longer wait time. + +# retrievedSourceHeader + +Retrieved Source + +# retrievedSourceWarningsHeader + +Retrieved Source Warnings + +# fullNameTableColumn + +FULL NAME + +# typeTableColumn + +TYPE + +# workspacePathTableColumn + +PROJECT PATH + +# NoResultsFound + +No results found + +# metadataNotFoundWarning + +WARNING: The following metadata isn’t in your org. If it’s not new, someone deleted it from the org. + +# columnNumberColumn + +COLUMN NUMBER + +# lineNumberColumn + +LINE NUMBER + +# errorColumn + +PROBLEM + +# nothingToRetrieve + +Specify a source path, manifest, metadata, or package names to retrieve. + +# wantsToRetrieveCustomFields + +Because you're retrieving one or more CustomFields, we're also retrieving the CustomObject to which it's associated. + +# retrieveWontDelete + +You currently have files deleted in your org. The retrieve command will NOT delete them from your local project + +# retrieveTargetDirOverlapsPackage + +The retrieve target directory [%s] overlaps one of your package directories. Specify a different retrieve target directory and try again. + +# apiVersionMsgDetailed + +%s v%s metadata from %s using the v%s SOAP API + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/spinner.json b/messages/spinner.json deleted file mode 100644 index 1777d69e2..000000000 --- a/messages/spinner.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "retrieve": { - "main": "Retrieving metadata from %s", - "componentSetBuild": "Preparing retrieve request", - "sendingRequest": "Sending request to org", - "polling": "Waiting for the org to respond" - } -} diff --git a/messages/spinner.md b/messages/spinner.md new file mode 100644 index 000000000..23390ee0f --- /dev/null +++ b/messages/spinner.md @@ -0,0 +1,15 @@ +# retrieve.main + +Retrieving metadata from %s + +# retrieve.componentSetBuild + +Preparing retrieve request + +# retrieve.sendingRequest + +Sending request to org + +# retrieve.polling + +Waiting for the org to respond diff --git a/messages/stash.json b/messages/stash.json deleted file mode 100644 index ea9f2cbdb..000000000 --- a/messages/stash.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "InvalidStashKey": "The stash key provided is invalid. Found: [%s].", - "InvalidStashFile": "Invalid stash file encountered. File has been renamed to: %s. Please re-run the command providing the --jobid parameter." -} diff --git a/messages/stash.md b/messages/stash.md new file mode 100644 index 000000000..2fbe65c04 --- /dev/null +++ b/messages/stash.md @@ -0,0 +1,7 @@ +# InvalidStashKey + +The stash key provided is invalid. Found: [%s]. + +# InvalidStashFile + +Invalid stash file encountered. File has been renamed to: %s. Re-run the command providing the --jobid parameter. diff --git a/messages/status.json b/messages/status.json deleted file mode 100644 index 1da0ffa24..000000000 --- a/messages/status.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "description": "list local changes and/or changes in a scratch org", - "LongDescription": "Lists changes that have been made locally, in a scratch org, or both.", - "examples": [ - "$ sfdx force:source:status -l", - "$ sfdx force:source:status -r", - "$ sfdx force:source:status", - "$ sfdx force:source:status -u me@example.com --json" - ], - "flags": { - "all": "list all the changes that have been made", - "allLong": "Lists all the changes that have been made.", - "local": "list the changes that have been made locally", - "localLong": "Lists the changes that have been made locally.", - "remote": "list the changes that have been made in the scratch org", - "remoteLong": "Lists the changes that have been made in the scratch org.", - "concise": "show only the changes that will be pushed or pulled; omits files that are forceignored" - }, - "humanSuccess": "Source Status", - "noResults": "No local or remote changes found." -} diff --git a/messages/status.md b/messages/status.md new file mode 100644 index 000000000..3c32c6c31 --- /dev/null +++ b/messages/status.md @@ -0,0 +1,37 @@ +# summary + +List changes that have been made locally, in an org, or both. + +# examples + +- List changes that have been made locally but not in the org with alias "myscratch": + + <%= config.bin %> <%= command.id %> --local --target-org myscratch + +- List changes that have been made in your default org but aren't reflected in your local project: + + <%= config.bin %> <%= command.id %> --remote + +# flags.local.summary + +List the changes that have been made locally. + +# flags.remote.summary + +List the changes that have been made in the org. + +# flags.concise.summary + +Show only the changes that will be pushed or pulled; omits files that are forceignored. + +# humanSuccess + +Source Status + +# noResults + +No local or remote changes found. + +# deprecation + +We plan to deprecate this command in the future. Try using the "%s" command instead. diff --git a/messages/tracking.json b/messages/tracking.json deleted file mode 100644 index 1bdb6d9c3..000000000 --- a/messages/tracking.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resetDescription": "reset local and remote source tracking\n\n WARNING: This command deletes or overwrites all existing source tracking files. Use with extreme caution. \n\nResets local and remote source tracking so that the CLI no longer registers differences between your local files and those in the org. When you next run force:source:status, the CLI returns no results, even though conflicts might actually exist. The CLI then resumes tracking new source changes as usual.\n\nUse the --revision parameter to reset source tracking to a specific revision number of an org source member. To get the revision number, query the SourceMember Tooling API object with the force:data:soql:query command. For example:\n $ sfdx force:data:soql:query -q \"SELECT MemberName, MemberType, RevisionCounter FROM SourceMember\" -t", - "clearDescription": "clear all local source tracking information\n\nWARNING: This command deletes or overwrites all existing source tracking files. Use with extreme caution.\n\nClears all local source tracking information. When you next run force:source:status, the CLI displays all local and remote files as changed, and any files with the same name are listed as conflicts.", - "nopromptDescription": "do not prompt for source tracking override confirmation", - "revisionDescription": "reset to a specific SourceMember revision counter number", - "promptMessage": "WARNING: This operation will modify all your local source tracking files. The operation can have unintended consequences on all the force:source commands. Are you sure you want to proceed (y/n)?", - "conflictMsg": "We couldn't complete the operation due to conflicts. Verify that you want to keep the existing versions, then run the command again with the --forceoverwrite (-f) option." -} diff --git a/messages/tracking.md b/messages/tracking.md new file mode 100644 index 000000000..3e0ed81fa --- /dev/null +++ b/messages/tracking.md @@ -0,0 +1,3 @@ +# conflictMsg + +We couldn't complete the operation due to conflicts. Verify that you want to keep the existing versions, then run the command again with the --forceoverwrite (-f) option. diff --git a/package.json b/package.json index 86297b58e..8a63885b7 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { "name": "@salesforce/plugin-source", "description": "Commands to interact with source formatted metadata", - "version": "2.8.0", + "version": "2.8.0-beta.5", "author": "Salesforce", "main": "lib/index.js", "bugs": "https://github.com/forcedotcom/cli/issues", "dependencies": { - "@oclif/core": "^2.4.0", + "@oclif/core": "^2.6.3", "@salesforce/apex-node": "^1.6.0", - "@salesforce/command": "^5.3.0", "@salesforce/core": "^3.33.6", "@salesforce/kit": "^1.9.0", - "@salesforce/source-deploy-retrieve": "^7.11.3", + "@salesforce/sf-plugins-core": "^2.2.4", + "@salesforce/source-deploy-retrieve": "^7.14.2", "@salesforce/source-tracking": "^2.2.24", "chalk": "^4.1.2", "got": "^11.8.6", @@ -26,15 +26,15 @@ "@salesforce/cli-plugins-testkit": "^3.3.0", "@salesforce/dev-config": "^3.1.0", "@salesforce/dev-scripts": "^4.1.3", - "@salesforce/plugin-command-reference": "^1.6.6", - "@salesforce/plugin-config": "^2.3.2", + "@salesforce/plugin-command-reference": "^2.3.2", "@salesforce/plugin-info": "^2.5.1", + "@salesforce/plugin-settings": "^1.4.2", "@salesforce/plugin-templates": "^55.4.4", "@salesforce/plugin-user": "^2.3.5", "@salesforce/prettier-config": "^0.0.2", "@salesforce/source-testkit": "^2.0.40", "@salesforce/ts-sinon": "1.4.2", - "@swc/core": "^1.3.42", + "@swc/core": "1.3.39", "@types/archiver": "^5.1.1", "@types/debug": "^4.1.7", "@types/proxy-from-env": "^1.0.1", @@ -54,6 +54,7 @@ "eslint-plugin-header": "^3.1.1", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsdoc": "^39.9.1", + "eslint-plugin-sf-plugin": "^1.14.0", "fast-glob": "^3.2.12", "husky": "^7.0.4", "mocha": "^9.1.3", @@ -94,7 +95,7 @@ "@oclif/plugin-help", "@salesforce/plugin-command-reference", "@salesforce/plugin-templates", - "@salesforce/plugin-config", + "@salesforce/plugin-settings", "@salesforce/plugin-user" ], "topics": { @@ -106,12 +107,6 @@ "subtopics": { "deploy": { "description": "interact with an active deploy request" - }, - "manifest": { - "description": "create a manifest to use in a deploy/retrieve" - }, - "tracking": { - "description": "reset and clear source tracking" } } }, @@ -149,8 +144,6 @@ "prepare": "sf-install", "test": "wireit", "test:nuts": "ts-node ./test/nuts/generateNuts.ts && nyc mocha \"**/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0", - "test:nuts:commands:other": "mocha \"test/nuts/ignored_list.nut.ts\" --slow 4500 --timeout 1200000 --retries 0 --parallel --jobs 20", - "test:nuts:convert": "cross-env PLUGIN_SOURCE_SEED_FILTER=convert ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:nuts:delete": "mocha \"test/nuts/delete.nut.ts\" --slow 4500 --timeout 1200000 --retries 0 --jobs 20", "test:nuts:deploy": "cross-env PLUGIN_SOURCE_SEED_FILTER=deploy PLUGIN_SOURCE_SEED_EXCLUDE=async ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:nuts:deploy:async": "cross-env PLUGIN_SOURCE_SEED_FILTER=deploy.async ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", @@ -161,7 +154,6 @@ "test:nuts:deploy:rest": "mocha \"test/nuts/REST/*.nut.ts\" --slow 3000 --timeout 1200000 --retries 0 --parallel --jobs 20", "test:nuts:deploy:sourcepath": "cross-env PLUGIN_SOURCE_SEED_FILTER=deploy.sourcepath ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:nuts:deploy:testlevel": "cross-env PLUGIN_SOURCE_SEED_FILTER=deploy.testlevel ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", - "test:nuts:manifest:create": "mocha \"test/nuts/create.nut.ts\" --slow 4500 --timeout 1200000 --retries 0 --jobs 20", "test:nuts:mdapi": "mocha \"test/nuts/mdapi.nut.ts\" --slow 3000 --timeout 1200000 --retries 0 --jobs 20", "test:nuts:retrieve": "cross-env PLUGIN_SOURCE_SEED_FILTER=retrieve ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:nuts:retrieve:metadata": "cross-env PLUGIN_SOURCE_SEED_FILTER=retrieve.metadata ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", @@ -178,7 +170,7 @@ "test:nuts:tracking:lwc": "mocha \"test/nuts/trackingCommands/lwc.nut.ts\" --slow 3000 --timeout 1200000 --retries 0 --jobs 20", "test:nuts:tracking:mpd": "mocha \"test/nuts/trackingCommands/mpd*\" --slow 3000 --timeout 1200000 --retries 0 -parallel --jobs 20", "test:nuts:tracking:remote": "mocha \"test/nuts/trackingCommands/remoteChanges.nut.ts\" --slow 3000 --timeout 1200000 --retries 0 --jobs 20", - "test:nuts:tracking:resetClear": "mocha \"test/nuts/trackingCommands/resetClear.nut.ts\" --slow 3000 --timeout 1200000 --retries 0 --jobs 20", + "test:nuts:deb": "mocha \"test/nuts/digitalExperienceBundle/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:only": "wireit", "test:watch": "mocha --watch \"./test/**/*.test.ts\"", "version": "oclif readme" diff --git a/schemas/force-source-deploy-cancel.json b/schemas/force-source-deploy-cancel.json new file mode 100644 index 000000000..71d9ce864 --- /dev/null +++ b/schemas/force-source-deploy-cancel.json @@ -0,0 +1,393 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeployCancelCommandResult", + "definitions": { + "DeployCancelCommandResult": { + "$ref": "#/definitions/MetadataApiDeployStatus" + }, + "MetadataApiDeployStatus": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RequestStatus" + }, + "success": { + "type": "boolean" + }, + "done": { + "type": "boolean" + }, + "canceledBy": { + "type": "string" + }, + "canceledByName": { + "type": "string" + }, + "checkOnly": { + "type": "boolean" + }, + "completedDate": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdByName": { + "type": "string" + }, + "createdDate": { + "type": "string" + }, + "details": { + "$ref": "#/definitions/DeployDetails" + }, + "errorMessage": { + "type": "string" + }, + "errorStatusCode": { + "type": "string" + }, + "ignoreWarnings": { + "type": "boolean" + }, + "lastModifiedDate": { + "type": "string" + }, + "numberComponentErrors": { + "type": "number" + }, + "numberComponentsDeployed": { + "type": "number" + }, + "numberComponentsTotal": { + "type": "number" + }, + "numberTestErrors": { + "type": "number" + }, + "numberTestsCompleted": { + "type": "number" + }, + "numberTestsTotal": { + "type": "number" + }, + "runTestsEnabled": { + "type": "boolean" + }, + "rollbackOnError": { + "type": "boolean" + }, + "startDate": { + "type": "string" + }, + "stateDetail": { + "type": "string" + } + }, + "required": [ + "checkOnly", + "createdBy", + "createdByName", + "createdDate", + "details", + "done", + "id", + "ignoreWarnings", + "lastModifiedDate", + "numberComponentErrors", + "numberComponentsDeployed", + "numberComponentsTotal", + "numberTestErrors", + "numberTestsCompleted", + "numberTestsTotal", + "rollbackOnError", + "runTestsEnabled", + "status", + "success" + ], + "additionalProperties": false, + "description": "Raw response returned from a checkDeployStatus call to the Metadata API" + }, + "RequestStatus": { + "type": "string", + "enum": ["Pending", "InProgress", "Succeeded", "SucceededPartial", "Failed", "Canceling", "Canceled"] + }, + "DeployDetails": { + "type": "object", + "properties": { + "componentFailures": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "componentSuccesses": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "runTestResult": { + "$ref": "#/definitions/RunTestResult" + } + }, + "additionalProperties": false + }, + "DeployMessage": { + "type": "object", + "properties": { + "changed": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "columnNumber": { + "type": "string" + }, + "componentType": { + "type": "string" + }, + "created": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "createdDate": { + "type": "string" + }, + "deleted": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "fileName": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lineNumber": { + "type": "string" + }, + "problem": { + "type": "string" + }, + "problemType": { + "type": "string", + "enum": ["Warning", "Error"] + }, + "success": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + } + }, + "required": ["changed", "created", "createdDate", "deleted", "fileName", "fullName", "success"], + "additionalProperties": false + }, + "RunTestResult": { + "type": "object", + "properties": { + "codeCoverage": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverage" + } + }, + { + "$ref": "#/definitions/CodeCoverage" + } + ] + }, + "codeCoverageWarnings": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverageWarnings" + } + }, + { + "$ref": "#/definitions/CodeCoverageWarnings" + } + ] + }, + "failures": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Failures" + } + }, + { + "$ref": "#/definitions/Failures" + } + ] + }, + "numFailures": { + "type": "string" + }, + "numTestsRun": { + "type": "string" + }, + "successes": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Successes" + } + }, + { + "$ref": "#/definitions/Successes" + } + ] + }, + "totalTime": { + "type": "string" + } + }, + "required": ["numFailures", "numTestsRun", "totalTime"], + "additionalProperties": false + }, + "CodeCoverage": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "locationsNotCovered": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/LocationsNotCovered" + } + }, + { + "$ref": "#/definitions/LocationsNotCovered" + } + ] + }, + "name": { + "type": "string" + }, + "numLocations": { + "type": "string" + }, + "numLocationsNotCovered": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "name", "numLocations", "numLocationsNotCovered", "type"], + "additionalProperties": false + }, + "LocationsNotCovered": { + "type": "object", + "properties": { + "column": { + "type": "string" + }, + "line": { + "type": "string" + }, + "numExecutions": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["column", "line", "numExecutions", "time"], + "additionalProperties": false + }, + "CodeCoverageWarnings": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": ["id", "message", "namespace"], + "additionalProperties": false + }, + "Failures": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "packageName": { + "type": "string" + }, + "stackTrace": { + "type": "string" + }, + "time": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "message", "methodName", "name", "packageName", "stackTrace", "time", "type"], + "additionalProperties": false + }, + "Successes": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["id", "methodName", "name", "time"], + "additionalProperties": false + } + } +} diff --git a/schemas/force-source-deploy-report.json b/schemas/force-source-deploy-report.json new file mode 100644 index 000000000..00770864f --- /dev/null +++ b/schemas/force-source-deploy-report.json @@ -0,0 +1,393 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeployReportCommandResult", + "definitions": { + "DeployReportCommandResult": { + "$ref": "#/definitions/MetadataApiDeployStatus" + }, + "MetadataApiDeployStatus": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RequestStatus" + }, + "success": { + "type": "boolean" + }, + "done": { + "type": "boolean" + }, + "canceledBy": { + "type": "string" + }, + "canceledByName": { + "type": "string" + }, + "checkOnly": { + "type": "boolean" + }, + "completedDate": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdByName": { + "type": "string" + }, + "createdDate": { + "type": "string" + }, + "details": { + "$ref": "#/definitions/DeployDetails" + }, + "errorMessage": { + "type": "string" + }, + "errorStatusCode": { + "type": "string" + }, + "ignoreWarnings": { + "type": "boolean" + }, + "lastModifiedDate": { + "type": "string" + }, + "numberComponentErrors": { + "type": "number" + }, + "numberComponentsDeployed": { + "type": "number" + }, + "numberComponentsTotal": { + "type": "number" + }, + "numberTestErrors": { + "type": "number" + }, + "numberTestsCompleted": { + "type": "number" + }, + "numberTestsTotal": { + "type": "number" + }, + "runTestsEnabled": { + "type": "boolean" + }, + "rollbackOnError": { + "type": "boolean" + }, + "startDate": { + "type": "string" + }, + "stateDetail": { + "type": "string" + } + }, + "required": [ + "checkOnly", + "createdBy", + "createdByName", + "createdDate", + "details", + "done", + "id", + "ignoreWarnings", + "lastModifiedDate", + "numberComponentErrors", + "numberComponentsDeployed", + "numberComponentsTotal", + "numberTestErrors", + "numberTestsCompleted", + "numberTestsTotal", + "rollbackOnError", + "runTestsEnabled", + "status", + "success" + ], + "additionalProperties": false, + "description": "Raw response returned from a checkDeployStatus call to the Metadata API" + }, + "RequestStatus": { + "type": "string", + "enum": ["Pending", "InProgress", "Succeeded", "SucceededPartial", "Failed", "Canceling", "Canceled"] + }, + "DeployDetails": { + "type": "object", + "properties": { + "componentFailures": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "componentSuccesses": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "runTestResult": { + "$ref": "#/definitions/RunTestResult" + } + }, + "additionalProperties": false + }, + "DeployMessage": { + "type": "object", + "properties": { + "changed": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "columnNumber": { + "type": "string" + }, + "componentType": { + "type": "string" + }, + "created": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "createdDate": { + "type": "string" + }, + "deleted": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "fileName": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lineNumber": { + "type": "string" + }, + "problem": { + "type": "string" + }, + "problemType": { + "type": "string", + "enum": ["Warning", "Error"] + }, + "success": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + } + }, + "required": ["changed", "created", "createdDate", "deleted", "fileName", "fullName", "success"], + "additionalProperties": false + }, + "RunTestResult": { + "type": "object", + "properties": { + "codeCoverage": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverage" + } + }, + { + "$ref": "#/definitions/CodeCoverage" + } + ] + }, + "codeCoverageWarnings": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverageWarnings" + } + }, + { + "$ref": "#/definitions/CodeCoverageWarnings" + } + ] + }, + "failures": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Failures" + } + }, + { + "$ref": "#/definitions/Failures" + } + ] + }, + "numFailures": { + "type": "string" + }, + "numTestsRun": { + "type": "string" + }, + "successes": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Successes" + } + }, + { + "$ref": "#/definitions/Successes" + } + ] + }, + "totalTime": { + "type": "string" + } + }, + "required": ["numFailures", "numTestsRun", "totalTime"], + "additionalProperties": false + }, + "CodeCoverage": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "locationsNotCovered": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/LocationsNotCovered" + } + }, + { + "$ref": "#/definitions/LocationsNotCovered" + } + ] + }, + "name": { + "type": "string" + }, + "numLocations": { + "type": "string" + }, + "numLocationsNotCovered": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "name", "numLocations", "numLocationsNotCovered", "type"], + "additionalProperties": false + }, + "LocationsNotCovered": { + "type": "object", + "properties": { + "column": { + "type": "string" + }, + "line": { + "type": "string" + }, + "numExecutions": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["column", "line", "numExecutions", "time"], + "additionalProperties": false + }, + "CodeCoverageWarnings": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": ["id", "message", "namespace"], + "additionalProperties": false + }, + "Failures": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "packageName": { + "type": "string" + }, + "stackTrace": { + "type": "string" + }, + "time": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "message", "methodName", "name", "packageName", "stackTrace", "time", "type"], + "additionalProperties": false + }, + "Successes": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["id", "methodName", "name", "time"], + "additionalProperties": false + } + } +} diff --git a/schemas/force-source-deploy.json b/schemas/force-source-deploy.json new file mode 100644 index 000000000..f565ac158 --- /dev/null +++ b/schemas/force-source-deploy.json @@ -0,0 +1,680 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeployCommandCombinedResult", + "definitions": { + "DeployCommandCombinedResult": { + "anyOf": [ + { + "$ref": "#/definitions/DeployCommandResult" + }, + { + "$ref": "#/definitions/DeployCommandAsyncResult" + } + ] + }, + "DeployCommandResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RequestStatus" + }, + "success": { + "type": "boolean" + }, + "done": { + "type": "boolean" + }, + "canceledBy": { + "type": "string" + }, + "canceledByName": { + "type": "string" + }, + "checkOnly": { + "type": "boolean" + }, + "completedDate": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdByName": { + "type": "string" + }, + "createdDate": { + "type": "string" + }, + "details": { + "$ref": "#/definitions/DeployDetails" + }, + "errorMessage": { + "type": "string" + }, + "errorStatusCode": { + "type": "string" + }, + "ignoreWarnings": { + "type": "boolean" + }, + "lastModifiedDate": { + "type": "string" + }, + "numberComponentErrors": { + "type": "number" + }, + "numberComponentsDeployed": { + "type": "number" + }, + "numberComponentsTotal": { + "type": "number" + }, + "numberTestErrors": { + "type": "number" + }, + "numberTestsCompleted": { + "type": "number" + }, + "numberTestsTotal": { + "type": "number" + }, + "runTestsEnabled": { + "type": "boolean" + }, + "rollbackOnError": { + "type": "boolean" + }, + "startDate": { + "type": "string" + }, + "stateDetail": { + "type": "string" + }, + "coverage": { + "$ref": "#/definitions/CoverageResultsFileInfo" + }, + "junit": { + "type": "string" + }, + "deletedSource": { + "type": "array", + "items": { + "$ref": "#/definitions/FileResponse" + } + }, + "deployedSource": { + "type": "array", + "items": { + "$ref": "#/definitions/FileResponse" + } + }, + "outboundFiles": { + "type": "array", + "items": { + "type": "string" + } + }, + "deploys": { + "type": "array", + "items": { + "$ref": "#/definitions/MetadataApiDeployStatus" + } + }, + "deletes": { + "type": "array", + "items": { + "$ref": "#/definitions/MetadataApiDeployStatus" + } + }, + "replacements": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "checkOnly", + "createdBy", + "createdByName", + "createdDate", + "deployedSource", + "deploys", + "details", + "done", + "id", + "ignoreWarnings", + "lastModifiedDate", + "numberComponentErrors", + "numberComponentsDeployed", + "numberComponentsTotal", + "numberTestErrors", + "numberTestsCompleted", + "numberTestsTotal", + "outboundFiles", + "rollbackOnError", + "runTestsEnabled", + "status", + "success" + ] + }, + "RequestStatus": { + "type": "string", + "enum": ["Pending", "InProgress", "Succeeded", "SucceededPartial", "Failed", "Canceling", "Canceled"] + }, + "DeployDetails": { + "type": "object", + "properties": { + "componentFailures": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "componentSuccesses": { + "anyOf": [ + { + "$ref": "#/definitions/DeployMessage" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/DeployMessage" + } + } + ] + }, + "runTestResult": { + "$ref": "#/definitions/RunTestResult" + } + }, + "additionalProperties": false + }, + "DeployMessage": { + "type": "object", + "properties": { + "changed": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "columnNumber": { + "type": "string" + }, + "componentType": { + "type": "string" + }, + "created": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "createdDate": { + "type": "string" + }, + "deleted": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + }, + "fileName": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lineNumber": { + "type": "string" + }, + "problem": { + "type": "string" + }, + "problemType": { + "type": "string", + "enum": ["Warning", "Error"] + }, + "success": { + "type": ["string", "boolean"], + "enum": ["true", "false", true, false] + } + }, + "required": ["changed", "created", "createdDate", "deleted", "fileName", "fullName", "success"], + "additionalProperties": false + }, + "RunTestResult": { + "type": "object", + "properties": { + "codeCoverage": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverage" + } + }, + { + "$ref": "#/definitions/CodeCoverage" + } + ] + }, + "codeCoverageWarnings": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/CodeCoverageWarnings" + } + }, + { + "$ref": "#/definitions/CodeCoverageWarnings" + } + ] + }, + "failures": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Failures" + } + }, + { + "$ref": "#/definitions/Failures" + } + ] + }, + "numFailures": { + "type": "string" + }, + "numTestsRun": { + "type": "string" + }, + "successes": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/Successes" + } + }, + { + "$ref": "#/definitions/Successes" + } + ] + }, + "totalTime": { + "type": "string" + } + }, + "required": ["numFailures", "numTestsRun", "totalTime"], + "additionalProperties": false + }, + "CodeCoverage": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "locationsNotCovered": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/LocationsNotCovered" + } + }, + { + "$ref": "#/definitions/LocationsNotCovered" + } + ] + }, + "name": { + "type": "string" + }, + "numLocations": { + "type": "string" + }, + "numLocationsNotCovered": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "name", "numLocations", "numLocationsNotCovered", "type"], + "additionalProperties": false + }, + "LocationsNotCovered": { + "type": "object", + "properties": { + "column": { + "type": "string" + }, + "line": { + "type": "string" + }, + "numExecutions": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["column", "line", "numExecutions", "time"], + "additionalProperties": false + }, + "CodeCoverageWarnings": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": ["id", "message", "namespace"], + "additionalProperties": false + }, + "Failures": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "packageName": { + "type": "string" + }, + "stackTrace": { + "type": "string" + }, + "time": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["id", "message", "methodName", "name", "packageName", "stackTrace", "time", "type"], + "additionalProperties": false + }, + "Successes": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "methodName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "time": { + "type": "string" + } + }, + "required": ["id", "methodName", "name", "time"], + "additionalProperties": false + }, + "CoverageResultsFileInfo": { + "type": "object", + "additionalProperties": false + }, + "FileResponse": { + "anyOf": [ + { + "$ref": "#/definitions/FileResponseSuccess" + }, + { + "$ref": "#/definitions/FileResponseFailure" + } + ] + }, + "FileResponseSuccess": { + "type": "object", + "properties": { + "fullName": { + "type": "string" + }, + "type": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "state": { + "type": "string", + "enum": ["Created", "Changed", "Unchanged", "Deleted"] + } + }, + "required": ["fullName", "state", "type"], + "additionalProperties": false + }, + "FileResponseFailure": { + "type": "object", + "properties": { + "fullName": { + "type": "string" + }, + "type": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "state": { + "type": "string", + "const": "Failed" + }, + "lineNumber": { + "type": "number" + }, + "columnNumber": { + "type": "number" + }, + "error": { + "type": "string" + }, + "problemType": { + "type": "string", + "enum": ["Warning", "Error"] + } + }, + "required": ["error", "fullName", "problemType", "state", "type"], + "additionalProperties": false + }, + "MetadataApiDeployStatus": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RequestStatus" + }, + "success": { + "type": "boolean" + }, + "done": { + "type": "boolean" + }, + "canceledBy": { + "type": "string" + }, + "canceledByName": { + "type": "string" + }, + "checkOnly": { + "type": "boolean" + }, + "completedDate": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdByName": { + "type": "string" + }, + "createdDate": { + "type": "string" + }, + "details": { + "$ref": "#/definitions/DeployDetails" + }, + "errorMessage": { + "type": "string" + }, + "errorStatusCode": { + "type": "string" + }, + "ignoreWarnings": { + "type": "boolean" + }, + "lastModifiedDate": { + "type": "string" + }, + "numberComponentErrors": { + "type": "number" + }, + "numberComponentsDeployed": { + "type": "number" + }, + "numberComponentsTotal": { + "type": "number" + }, + "numberTestErrors": { + "type": "number" + }, + "numberTestsCompleted": { + "type": "number" + }, + "numberTestsTotal": { + "type": "number" + }, + "runTestsEnabled": { + "type": "boolean" + }, + "rollbackOnError": { + "type": "boolean" + }, + "startDate": { + "type": "string" + }, + "stateDetail": { + "type": "string" + } + }, + "required": [ + "checkOnly", + "createdBy", + "createdByName", + "createdDate", + "details", + "done", + "id", + "ignoreWarnings", + "lastModifiedDate", + "numberComponentErrors", + "numberComponentsDeployed", + "numberComponentsTotal", + "numberTestErrors", + "numberTestsCompleted", + "numberTestsTotal", + "rollbackOnError", + "runTestsEnabled", + "status", + "success" + ], + "additionalProperties": false, + "description": "Raw response returned from a checkDeployStatus call to the Metadata API" + }, + "DeployCommandAsyncResult": { + "type": "object", + "properties": { + "done": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "const": "Queued" + }, + "status": { + "type": "string", + "const": "Queued" + }, + "timedOut": { + "type": "boolean" + }, + "outboundFiles": { + "type": "array", + "items": { + "type": "string" + } + }, + "deploys": { + "type": "array", + "items": { + "$ref": "#/definitions/DeployAsyncStatus" + } + } + }, + "required": ["deploys", "done", "id", "outboundFiles", "state", "status", "timedOut"], + "additionalProperties": false + }, + "DeployAsyncStatus": { + "type": "object", + "properties": { + "done": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "const": "Queued" + }, + "status": { + "type": "string", + "const": "Queued" + }, + "timedOut": { + "type": "boolean" + } + }, + "required": ["done", "id", "state", "status", "timedOut"], + "additionalProperties": false + } + } +} diff --git a/schemas/force-source-pull.json b/schemas/force-source-pull.json new file mode 100644 index 000000000..73cfe82af --- /dev/null +++ b/schemas/force-source-pull.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/PullResponse", + "definitions": { + "PullResponse": { + "type": "object", + "properties": { + "pulledSource": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filePath": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "state": { + "type": "string", + "enum": ["Created", "Changed", "Unchanged", "Deleted", "Failed"] + }, + "type": { + "type": "string" + } + }, + "required": ["fullName", "state", "type"], + "additionalProperties": false + } + } + }, + "required": ["pulledSource"], + "additionalProperties": false + } + } +} diff --git a/schemas/force-source-push.json b/schemas/force-source-push.json new file mode 100644 index 000000000..02bafe8d2 --- /dev/null +++ b/schemas/force-source-push.json @@ -0,0 +1,45 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/PushResponse", + "definitions": { + "PushResponse": { + "type": "object", + "properties": { + "pushedSource": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filePath": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "state": { + "type": "string", + "enum": ["Created", "Changed", "Unchanged", "Deleted", "Failed"] + }, + "type": { + "type": "string" + } + }, + "required": ["fullName", "state", "type"], + "additionalProperties": false + } + }, + "replacements": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": ["pushedSource"], + "additionalProperties": false + } + } +} diff --git a/schemas/force-source-retrieve.json b/schemas/force-source-retrieve.json new file mode 100644 index 000000000..26f224cfb --- /dev/null +++ b/schemas/force-source-retrieve.json @@ -0,0 +1,241 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/RetrieveCommandResult", + "definitions": { + "RetrieveCommandResult": { + "type": "object", + "properties": { + "inboundFiles": { + "type": "array", + "items": { + "$ref": "#/definitions/FileResponse" + } + }, + "packages": { + "type": "array", + "items": { + "$ref": "#/definitions/PackageRetrieval" + } + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/RetrieveMessage" + } + }, + "response": { + "$ref": "#/definitions/MetadataApiRetrieveStatus" + } + }, + "required": ["inboundFiles", "packages", "warnings", "response"], + "additionalProperties": false + }, + "FileResponse": { + "anyOf": [ + { + "$ref": "#/definitions/FileResponseSuccess" + }, + { + "$ref": "#/definitions/FileResponseFailure" + } + ] + }, + "FileResponseSuccess": { + "type": "object", + "properties": { + "fullName": { + "type": "string" + }, + "type": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "state": { + "type": "string", + "enum": ["Created", "Changed", "Unchanged", "Deleted"] + } + }, + "required": ["fullName", "state", "type"], + "additionalProperties": false + }, + "FileResponseFailure": { + "type": "object", + "properties": { + "fullName": { + "type": "string" + }, + "type": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "state": { + "type": "string", + "const": "Failed" + }, + "lineNumber": { + "type": "number" + }, + "columnNumber": { + "type": "number" + }, + "error": { + "type": "string" + }, + "problemType": { + "type": "string", + "enum": ["Warning", "Error"] + } + }, + "required": ["error", "fullName", "problemType", "state", "type"], + "additionalProperties": false + }, + "PackageRetrieval": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "path": { + "type": "string" + } + }, + "required": ["name", "path"], + "additionalProperties": false + }, + "RetrieveMessage": { + "type": "object", + "properties": { + "fileName": { + "type": "string" + }, + "problem": { + "type": "string" + } + }, + "required": ["fileName", "problem"], + "additionalProperties": false + }, + "MetadataApiRetrieveStatus": { + "type": "object", + "properties": { + "done": { + "type": "boolean" + }, + "fileProperties": { + "anyOf": [ + { + "$ref": "#/definitions/FileProperties" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/FileProperties" + } + } + ] + }, + "id": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RequestStatus" + }, + "success": { + "type": "boolean" + }, + "messages": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/RetrieveMessage" + } + }, + { + "$ref": "#/definitions/RetrieveMessage" + } + ] + }, + "zipFile": { + "type": "string", + "description": "`base64` encoded string" + } + }, + "required": ["done", "fileProperties", "id", "status", "success", "zipFile"], + "additionalProperties": false, + "description": "Raw response returned from a checkRetrieveStatus call to the Metadata API" + }, + "FileProperties": { + "type": "object", + "properties": { + "createdById": { + "type": "string" + }, + "createdByName": { + "type": "string" + }, + "createdDate": { + "type": "string" + }, + "fileName": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lastModifiedById": { + "type": "string" + }, + "lastModifiedByName": { + "type": "string" + }, + "lastModifiedDate": { + "type": "string" + }, + "manageableState": { + "type": "string", + "enum": [ + "beta", + "deleted", + "deprecated", + "deprecatedEditable", + "installed", + "installedEditable", + "released", + "unmanaged" + ] + }, + "namespacePrefix": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "createdById", + "createdByName", + "createdDate", + "fileName", + "fullName", + "id", + "lastModifiedById", + "lastModifiedByName", + "lastModifiedDate", + "type" + ], + "additionalProperties": false + }, + "RequestStatus": { + "type": "string", + "enum": ["Pending", "InProgress", "Succeeded", "SucceededPartial", "Failed", "Canceling", "Canceled"] + } + } +} diff --git a/schemas/force-source-status.json b/schemas/force-source-status.json new file mode 100644 index 000000000..9bbf5689e --- /dev/null +++ b/schemas/force-source-status.json @@ -0,0 +1,63 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/StatusCommandResult", + "definitions": { + "StatusCommandResult": { + "type": "array", + "items": { + "$ref": "#/definitions/StatusResult" + } + }, + "StatusResult": { + "type": "object", + "properties": { + "state": { + "type": "string", + "enum": [ + "Local Deleted", + "Local Add", + "Local Changed", + "Local Unchanged", + "Remote Deleted", + "Remote Add", + "Remote Changed", + "Remote Unchanged", + "Local Deleted (Conflict)", + "Local Add (Conflict)", + "Local Changed (Conflict)", + "Local Unchanged (Conflict)", + "Remote Deleted (Conflict)", + "Remote Add (Conflict)", + "Remote Changed (Conflict)", + "Remote Unchanged (Conflict)" + ] + }, + "fullName": { + "type": "string" + }, + "type": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "ignored": { + "type": "boolean" + }, + "conflict": { + "type": "boolean" + }, + "actualState": { + "type": "string", + "enum": ["Deleted", "Add", "Changed", "Unchanged"] + }, + "origin": { + "type": "string", + "enum": ["Local", "Remote"] + } + }, + "required": ["state", "fullName", "type", "origin"], + "additionalProperties": false + } + } +} diff --git a/schemas/force.json b/schemas/force.json new file mode 100644 index 000000000..77533e5a6 --- /dev/null +++ b/schemas/force.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/ForceCommandResult", + "definitions": { + "ForceCommandResult": { + "type": "object", + "properties": { + "apiVersion": { + "type": "string" + } + }, + "required": ["apiVersion"], + "additionalProperties": false + } + } +} diff --git a/src/commands/force.ts b/src/commands/force.ts index 9a5be658a..99d1622ed 100644 --- a/src/commands/force.ts +++ b/src/commands/force.ts @@ -8,12 +8,12 @@ // This is a doc command /* istanbul ignore file */ -import { SfdxCommand } from '@salesforce/command'; import got from 'got'; import { Help } from '@oclif/core'; import * as ProxyAgent from 'proxy-agent'; import { getProxyForUrl } from 'proxy-from-env'; import { ConfigAggregator } from '@salesforce/core'; +import { SfCommand } from '@salesforce/sf-plugins-core'; const getAsciiSignature = (apiVersion: string): string => ` DX DX DX @@ -70,18 +70,22 @@ const getCurrentApiVersion = async (): Promise => { ).versions.selected.toString()}.0`; }; -export class ForceCommand extends SfdxCommand { +export type ForceCommandResult = { apiVersion: string }; + +export class ForceCommand extends SfCommand { public static readonly hidden = true; + public static readonly examples = []; + // eslint-disable-next-line sf-plugin/no-hardcoded-messages-commands + public static readonly summary = 'Display the ASCII art logo for the Salesforce CLI'; - public async run(): Promise<{ apiVersion: string }> { + public async run(): Promise { const apiVersion = await getCurrentApiVersion(); - this.ux.log(getAsciiSignature(apiVersion)); + this.log(getAsciiSignature(apiVersion)); return { apiVersion }; } // overrides the help so that it shows the help for the `force` topic and not "help" for this command protected _help(): void { - // @ts-expect-error type mismatch between oclif/core v1 and v2 const help = new Help(this.config); // We need to include force in the args for topics to be shown void help.showHelp(process.argv.slice(2)); diff --git a/src/commands/force/mdapi/convert.ts b/src/commands/force/mdapi/convert.ts deleted file mode 100644 index 54fc3d589..000000000 --- a/src/commands/force/mdapi/convert.ts +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import { ComponentSetBuilder, ConvertResult, MetadataConverter } from '@salesforce/source-deploy-retrieve'; -import { Optional } from '@salesforce/ts-types'; -import { SourceCommand } from '../../../sourceCommand'; -import { ConvertCommandResult, ConvertResultFormatter } from '../../../formatters/mdapi/convertResultFormatter'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.convert'); - -export class Convert extends SourceCommand { - public static aliases = ['force:mdapi:beta:convert']; - public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresProject = true; - public static readonly flagsConfig: FlagsConfig = { - rootdir: flags.directory({ - char: 'r', - description: messages.getMessage('flags.rootdir'), - longDescription: messages.getMessage('flagsLong.rootdir'), - required: true, - }), - outputdir: flags.directory({ - char: 'd', - description: messages.getMessage('flags.outputdir'), - longDescription: messages.getMessage('flagsLong.outputdir'), - }), - manifest: flags.string({ - char: 'x', - description: messages.getMessage('flags.manifest'), - longDescription: messages.getMessage('flagsLong.manifest'), - }), - metadatapath: flags.array({ - char: 'p', - description: messages.getMessage('flags.metadatapath'), - longDescription: messages.getMessage('flagsLong.metadatapath'), - exclusive: ['manifest', 'metadata'], - }), - metadata: flags.array({ - char: 'm', - description: messages.getMessage('flags.metadata'), - longDescription: messages.getMessage('flagsLong.metadata'), - exclusive: ['manifest', 'metadatapath'], - }), - }; - - private rootDir: string; - private outputDir: string; - private convertResult: ConvertResult; - - public async run(): Promise { - await this.convert(); - this.resolveSuccess(); - return this.formatResult(); - } - - protected async convert(): Promise { - this.rootDir = this.resolveRootDir(this.getFlag('rootdir')); - this.outputDir = this.resolveOutputDir(this.getFlag('outputdir')); - const metadatapath = this.resolveMetadataPaths(this.getFlag('metadatapath')); - const manifest = this.resolveManifest(this.getFlag('manifest')); - const metadata = this.getFlag('metadata'); - - let paths: string[]; - if (metadatapath) { - paths = metadatapath; - } else if (!manifest && !metadata) { - paths = [this.rootDir]; - } - - this.componentSet = await ComponentSetBuilder.build({ - sourcepath: paths, - manifest: manifest && { - manifestPath: manifest, - directoryPaths: [this.rootDir], - }, - metadata: metadata && { - metadataEntries: metadata, - directoryPaths: [this.rootDir], - }, - }); - - const numOfComponents = this.componentSet.getSourceComponents().toArray().length; - if (numOfComponents > 0) { - this.ux.startSpinner(`Converting ${numOfComponents} metadata components`); - - const converter = new MetadataConverter(); - this.convertResult = await converter.convert(this.componentSet, 'source', { - type: 'directory', - outputDirectory: this.outputDir, - genUniqueDir: false, - }); - this.ux.stopSpinner(); - } - } - - // No-op. Any failure would throw an error. If no error, it's successful. - // The framework provides this behavior. - /* eslint-disable-next-line @typescript-eslint/no-empty-function, class-methods-use-this */ - protected resolveSuccess(): void {} - - protected formatResult(): ConvertCommandResult { - const formatter = new ConvertResultFormatter(this.logger, this.ux, this.convertResult); - - if (!this.isJsonOutput()) { - formatter.display(); - } - return formatter.getJson(); - } - - private resolveRootDir(rootDir: string): string { - return this.ensureFlagPath({ - flagName: 'rootdir', - path: rootDir, - type: 'dir', - throwOnENOENT: true, - }); - } - - private resolveOutputDir(outputDir?: string): string { - return this.ensureFlagPath({ - flagName: 'outputdir', - path: outputDir || this.project.getDefaultPackage().path, - type: 'dir', - }); - } - - private resolveManifest(manifestPath?: string): Optional { - if (manifestPath?.length) { - return this.ensureFlagPath({ - flagName: 'manifest', - path: manifestPath, - type: 'file', - throwOnENOENT: true, - }); - } - } - - private resolveMetadataPaths(metadataPaths: string[]): Optional { - const resolvedMetadataPaths: string[] = []; - - if (metadataPaths?.length) { - metadataPaths.forEach((mdPath) => { - if (mdPath?.length) { - resolvedMetadataPaths.push( - this.ensureFlagPath({ - flagName: 'metadatapath', - path: mdPath, - type: 'any', - throwOnENOENT: true, - }) - ); - } - }); - } - return resolvedMetadataPaths.length ? resolvedMetadataPaths : undefined; - } -} diff --git a/src/commands/force/mdapi/deploy.ts b/src/commands/force/mdapi/deploy.ts index e9578d6d3..036710351 100644 --- a/src/commands/force/mdapi/deploy.ts +++ b/src/commands/force/mdapi/deploy.ts @@ -4,11 +4,18 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { EOL } from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; import { Duration, env } from '@salesforce/kit'; -import { Messages } from '@salesforce/core'; +import { Lifecycle, Messages, Org } from '@salesforce/core'; import { DeployVersionData, MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; +import { + arrayWithDeprecation, + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand, getCoverageFormattersOptions, reportsFormatters, TestLevel } from '../../../deployCommand'; import { DeployCommandAsyncResult } from '../../../formatters/source/deployAsyncResultFormatter'; import { MdDeployResult, MdDeployResultFormatter } from '../../../formatters/mdapi/mdDeployResultFormatter'; @@ -23,104 +30,118 @@ const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.deploy') const deployMessages = Messages.loadMessages('@salesforce/plugin-source', 'deployCommand'); const xorFlags = ['zipfile', 'validateddeployrequestid', 'deploydir']; +export type DeployResult = MdDeployResult | DeployCommandAsyncResult; +const replacement = 'project deploy start'; export class Deploy extends DeployCommand { - public static aliases = ['force:mdapi:beta:deploy']; - public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - checkonly: flags.boolean({ + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly summary = messages.getMessage('summary'); + public static readonly examples = messages.getMessages('examples'); + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + checkonly: Flags.boolean({ char: 'c', - description: messages.getMessage('flags.checkOnly'), - longDescription: messages.getMessage('flagsLong.checkOnly'), + description: messages.getMessage('flags.checkOnly.description'), + summary: messages.getMessage('flags.checkOnly.summary'), }), - deploydir: flags.directory({ + deploydir: Flags.directory({ char: 'd', - description: messages.getMessage('flags.deployDir'), - longDescription: messages.getMessage('flagsLong.deployDir'), + description: messages.getMessage('flags.deployDir.description'), + summary: messages.getMessage('flags.deployDir.summary'), exactlyOne: xorFlags, }), - wait: flags.minutes({ + wait: Flags.duration({ char: 'w', - description: messages.getMessage('flags.wait', [0]), - longDescription: messages.getMessage('flagsLong.wait', [0]), + unit: 'minutes', + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), default: Duration.minutes(0), min: -1, }), - testlevel: flags.enum({ + testlevel: Flags.string({ char: 'l', - description: messages.getMessage('flags.testLevel'), - longDescription: messages.getMessage('flagsLong.testLevel'), + description: messages.getMessage('flags.testLevel.description'), + summary: messages.getMessage('flags.testLevel.summary'), options: ['NoTestRun', 'RunSpecifiedTests', 'RunLocalTests', 'RunAllTestsInOrg'], }), - runtests: flags.array({ + runtests: arrayWithDeprecation({ char: 'r', - description: messages.getMessage('flags.runTests'), - longDescription: messages.getMessage('flagsLong.runTests'), + summary: messages.getMessage('flags.runTests.summary'), }), - ignoreerrors: flags.boolean({ + ignoreerrors: Flags.boolean({ char: 'o', - description: messages.getMessage('flags.ignoreErrors'), - longDescription: messages.getMessage('flagsLong.ignoreErrors'), + description: messages.getMessage('flags.ignoreErrors.description'), + summary: messages.getMessage('flags.ignoreErrors.summary'), }), - ignorewarnings: flags.boolean({ + ignorewarnings: Flags.boolean({ char: 'g', - description: messages.getMessage('flags.ignoreWarnings'), - longDescription: messages.getMessage('flagsLong.ignoreWarnings'), + description: messages.getMessage('flags.ignoreWarnings.description'), + summary: messages.getMessage('flags.ignoreWarnings.summary'), }), - validateddeployrequestid: flags.id({ + validateddeployrequestid: Flags.salesforceId({ char: 'q', - description: messages.getMessage('flags.validatedDeployRequestId'), - longDescription: messages.getMessage('flagsLong.validatedDeployRequestId'), + length: 'both', + startsWith: '0Af', + description: messages.getMessage('flags.validatedDeployRequestId.description'), + summary: messages.getMessage('flags.validatedDeployRequestId.summary'), exactlyOne: xorFlags, exclusive: ['testlevel', 'runtests', 'checkonly'], - validate: DeployCommand.isValidDeployId, }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), - longDescription: messages.getMessage('flagsLong.verbose'), + verbose: Flags.boolean({ + description: messages.getMessage('flags.verbose.description'), + summary: messages.getMessage('flags.verbose.summary'), }), - zipfile: flags.filepath({ + zipfile: Flags.file({ char: 'f', - description: messages.getMessage('flags.zipFile'), - longDescription: messages.getMessage('flagsLong.zipFile'), + description: messages.getMessage('flags.zipFile.description'), + summary: messages.getMessage('flags.zipFile.summary'), exactlyOne: xorFlags, }), - singlepackage: flags.boolean({ + singlepackage: Flags.boolean({ char: 's', - description: messages.getMessage('flags.singlePackage'), - longDescription: messages.getMessage('flagsLong.singlePackage'), + description: messages.getMessage('flags.singlePackage.description'), + summary: messages.getMessage('flags.singlePackage.summary'), }), - soapdeploy: flags.boolean({ - description: messages.getMessage('flags.soapDeploy'), - longDescription: messages.getMessage('flagsLong.soapDeploy'), + soapdeploy: Flags.boolean({ + description: messages.getMessage('flags.soapDeploy.description'), + summary: messages.getMessage('flags.soapDeploy.summary'), }), - purgeondelete: flags.boolean({ - description: messages.getMessage('flags.purgeOnDelete'), + purgeondelete: Flags.boolean({ + summary: messages.getMessage('flags.purgeOnDelete.summary'), }), - concise: flags.builtin({ - description: messages.getMessage('flags.concise'), + concise: Flags.boolean({ + summary: messages.getMessage('flags.concise.summary'), }), - resultsdir: flags.directory({ - description: messages.getMessage('flags.resultsDir'), + resultsdir: Flags.directory({ + summary: messages.getMessage('flags.resultsDir.summary'), }), - coverageformatters: flags.array({ - description: messages.getMessage('flags.coverageFormatters'), + coverageformatters: arrayWithDeprecation({ + summary: messages.getMessage('flags.coverageFormatters.summary'), options: reportsFormatters, helpValue: reportsFormatters.join(','), }), - junit: flags.boolean({ description: messages.getMessage('flags.junit') }), + junit: Flags.boolean({ summary: messages.getMessage('flags.junit.summary') }), }; - public async run(): Promise { + private flags: Interfaces.InferredFlags; + private org: Org; + + public async run(): Promise { + this.flags = (await this.parse(Deploy)).flags; + this.org = this.flags['target-org']; await this.deploy(); this.resolveSuccess(); return this.formatResult(); } protected async deploy(): Promise { - const waitFlag = this.getFlag('wait'); + const waitFlag = this.flags.wait; const waitDuration = waitFlag.minutes === -1 ? Duration.days(7) : waitFlag; this.isAsync = waitDuration.quantity === 0; @@ -129,12 +150,15 @@ export class Deploy extends DeployCommand { this.warn(messages.getMessage('asyncCoverageJunitWarning')); } if (this.flags.validateddeployrequestid) { - this.deployResult = await this.deployRecentValidation(); + this.deployResult = await this.deployRecentValidation( + this.flags.validateddeployrequestid, + this.org.getConnection() + ); return; } const deploymentOptions = this.flags.zipfile - ? { zipPath: this.flags.zipfile as string } - : { mdapiPath: this.flags.deploydir as string }; + ? { zipPath: this.flags.zipfile } + : { mdapiPath: this.flags.deploydir }; const username = this.org.getUsername(); // still here? we need to deploy a zip file then @@ -144,33 +168,38 @@ export class Deploy extends DeployCommand { apiOptions: { // properties that will always have values ...{ - purgeOnDelete: this.getFlag('purgeondelete', false), - ignoreWarnings: this.getFlag('ignorewarnings', false), - rollbackOnError: !this.getFlag('ignoreerrors', false), - checkOnly: this.getFlag('checkonly', false), - singlePackage: this.getFlag('singlepackage', false), + purgeOnDelete: this.flags.purgeondelete ?? false, + ignoreWarnings: this.flags.ignorewarnings ?? false, + rollbackOnError: !this.flags.ignoreerrors ?? false, + checkOnly: this.flags.checkonly ?? false, + singlePackage: this.flags.singlepackage ?? false, rest: this.isRest, }, // if runTests is defaulted as 'NoTestRun' and deploying to prod, you'll get this error // https://github.com/forcedotcom/cli/issues/1542 - // add additional properties conditionally () - ...(this.getFlag('testlevel') ? { testLevel: this.getFlag('testlevel') } : {}), - ...(this.getFlag('runtests') ? { runTests: this.getFlag('runtests') } : {}), + // add additional properties conditionally + ...(this.flags.testlevel + ? { + testLevel: this.flags.testlevel as TestLevel, + } + : {}), + ...(this.flags.runtests ? { runTests: this.flags.runtests } : {}), }, }); + // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionDeploy', async (apiData: DeployVersionData) => { - this.ux.log(deployMessages.getMessage('apiVersionMsgBasic', [username, apiData.apiVersion, apiData.webService])); + Lifecycle.getInstance().on('apiVersionDeploy', async (apiData: DeployVersionData) => { + this.log(deployMessages.getMessage('apiVersionMsgBasic', [username, apiData.apiVersion, apiData.webService])); }); await deploy.start(); this.asyncDeployResult = { id: deploy.id }; this.updateDeployId(deploy.id); if (!this.isAsync) { - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux); + ? new DeployProgressBarFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })) + : new DeployProgressStatusFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })); progressFormatter.progress(deploy); } this.displayDeployId(deploy.id); @@ -180,32 +209,40 @@ export class Deploy extends DeployCommand { protected formatResult(): MdDeployResult | DeployCommandAsyncResult { this.resultsDir = this.resolveOutputDir( - this.getFlag('coverageformatters', undefined), - this.getFlag('junit'), - this.getFlag('resultsdir'), + this.flags.coverageformatters, + this.flags.junit, + this.flags.resultsdir, this.deployResult?.response?.id, true ); const formatterOptions: ResultFormatterOptions = { - concise: this.getFlag('concise', false), - verbose: this.getFlag('verbose', false), + concise: this.flags.concise ?? false, + verbose: this.flags.verbose ?? false, username: this.org.getUsername(), - coverageOptions: getCoverageFormattersOptions(this.getFlag('coverageformatters', undefined)), - junitTestResults: this.flags.junit as boolean, + coverageOptions: getCoverageFormattersOptions(this.flags.coverageformatters), + junitTestResults: this.flags.junit, resultsDir: this.resultsDir, - testsRan: this.getFlag('testlevel', 'NoTestRun') !== 'NoTestRun', + testsRan: (this.flags.testlevel ?? 'NoTestRun') !== 'NoTestRun', }; const formatter = this.isAsync - ? new MdDeployAsyncResultFormatter(this.logger, this.ux, formatterOptions, this.asyncDeployResult) - : new MdDeployResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult); + ? new MdDeployAsyncResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.asyncDeployResult + ) + : new MdDeployResultFormatter(new Ux({ jsonEnabled: this.jsonEnabled() }), formatterOptions, this.deployResult); if (!this.isAsync) { - this.maybeCreateRequestedReports(); + this.maybeCreateRequestedReports({ + coverageformatters: this.flags.coverageformatters, + junit: this.flags.junit, + org: this.org, + }); } // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } diff --git a/src/commands/force/mdapi/deploy/cancel.ts b/src/commands/force/mdapi/deploy/cancel.ts index 807788932..2d1b34533 100644 --- a/src/commands/force/mdapi/deploy/cancel.ts +++ b/src/commands/force/mdapi/deploy/cancel.ts @@ -4,12 +4,17 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ - -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages, SfError } from '@salesforce/core'; +import { Connection, Messages, SfError } from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { RequestStatus } from '@salesforce/source-deploy-retrieve'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand } from '../../../../deployCommand'; import { DeployCancelCommandResult, @@ -17,47 +22,56 @@ import { } from '../../../../formatters/deployCancelResultFormatter'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'md.cancel', [ - 'CancelFailed', - 'description', - 'examples', - 'flags.wait', - 'flags.waitLong', - 'flags.jobid', -]); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.cancel'); + +const replacement = 'project deploy cancel'; export class Cancel extends DeployCommand { public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - wait: flags.minutes({ + public static readonly summary = messages.getMessage('summary'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + wait: Flags.duration({ char: 'w', + unit: 'minutes', default: Duration.minutes(DeployCommand.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flags.waitLong'), + min: 1, + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), }), - jobid: flags.id({ + jobid: Flags.salesforceId({ char: 'i', - description: messages.getMessage('flags.jobid'), - validate: DeployCommand.isValidDeployId, + length: 'both', + startsWith: '0Af', + summary: messages.getMessage('flags.jobid.summary'), }), }; + private flags: Interfaces.InferredFlags; + private conn: Connection; public async run(): Promise { + this.flags = (await this.parse(Cancel)).flags; + this.conn = this.flags['target-org'].getConnection(this.flags['api-version']); await this.cancel(); this.resolveSuccess(); return this.formatResult(); } protected async cancel(): Promise { - const deployId = this.resolveDeployId(this.getFlag('jobid')); + const deployId = this.resolveDeployId(this.flags.jobid); try { - const deploy = this.createDeploy(deployId); + const deploy = this.createDeploy(this.conn, deployId); await deploy.cancel(); - this.deployResult = await this.poll(deployId); + this.deployResult = await this.poll(this.conn, deployId); } catch (e) { const err = e as Error; throw new SfError(messages.getMessage('CancelFailed', [err.message]), 'CancelFailed'); @@ -72,8 +86,8 @@ export class Cancel extends DeployCommand { } protected formatResult(): DeployCancelCommandResult { - const formatter = new DeployCancelResultFormatter(this.logger, this.ux, this.deployResult); - if (!this.isJsonOutput()) { + const formatter = new DeployCancelResultFormatter(new Ux({ jsonEnabled: this.jsonEnabled() }), this.deployResult); + if (!this.jsonEnabled()) { formatter.display(); } return formatter.getJson(); diff --git a/src/commands/force/mdapi/deploy/report.ts b/src/commands/force/mdapi/deploy/report.ts index 1279f26da..fa517928a 100644 --- a/src/commands/force/mdapi/deploy/report.ts +++ b/src/commands/force/mdapi/deploy/report.ts @@ -4,11 +4,18 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { EOL } from 'os'; -import { Messages } from '@salesforce/core'; -import { flags, FlagsConfig } from '@salesforce/command'; +import { Messages, Org } from '@salesforce/core'; import { Duration, env } from '@salesforce/kit'; import { RequestStatus } from '@salesforce/source-deploy-retrieve'; +import { + arrayWithDeprecation, + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { MdDeployResult, MdDeployResultFormatter } from '../../../../formatters/mdapi/mdDeployResultFormatter'; import { DeployCommand, getCoverageFormattersOptions, reportsFormatters } from '../../../../deployCommand'; import { ProgressFormatter } from '../../../../formatters/progressFormatter'; @@ -18,45 +25,59 @@ import { DeployProgressStatusFormatter } from '../../../../formatters/deployProg Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.deployreport'); +const replacement = 'project deploy report'; + export class Report extends DeployCommand { - public static aliases = ['force:mdapi:beta:deploy:report']; + public static readonly summary = messages.getMessage('summary'); public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(EOL); - public static readonly requiresUsername = true; - - public static readonly flagsConfig: FlagsConfig = { - wait: flags.minutes({ + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + wait: Flags.duration({ char: 'w', - default: Duration.minutes(0), - min: Duration.minutes(-1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + defaultValue: 0, + min: -1, + unit: 'minutes', + summary: messages.getMessage('flags.wait.summary'), }), - jobid: flags.id({ + jobid: Flags.salesforceId({ char: 'i', - description: messages.getMessage('flags.jobId'), - longDescription: messages.getMessage('flagsLong.jobId'), - validate: DeployCommand.isValidDeployId, + startsWith: '0Af', + length: 'both', + description: messages.getMessage('flags.jobId.description'), + summary: messages.getMessage('flags.jobId.summary'), }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), - longDescription: messages.getMessage('flagsLong.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), - concise: flags.builtin({ - description: messages.getMessage('flags.concise'), + concise: Flags.boolean({ + summary: messages.getMessage('flags.concise.summary'), }), - resultsdir: flags.directory({ - description: messages.getMessage('flags.resultsDir'), + resultsdir: Flags.directory({ + summary: messages.getMessage('flags.resultsDir.summary'), }), - coverageformatters: flags.array({ - description: messages.getMessage('flags.coverageFormatters'), + coverageformatters: arrayWithDeprecation({ + summary: messages.getMessage('flags.coverageFormatters.summary'), options: reportsFormatters, helpValue: reportsFormatters.join(','), }), - junit: flags.boolean({ description: messages.getMessage('flags.junit') }), + junit: Flags.boolean({ summary: messages.getMessage('flags.junit.summary') }), }; + private flags: Interfaces.InferredFlags; + private org: Org; + public async run(): Promise { + this.flags = (await this.parse(Report)).flags; + this.org = this.flags['target-org']; + await this.doReport(); this.resolveSuccess(); return this.formatResult(); @@ -64,33 +85,33 @@ export class Report extends DeployCommand { protected async doReport(): Promise { if (this.flags.verbose) { - this.ux.log(messages.getMessage('usernameOutput', [this.org.getUsername()])); + this.log(messages.getMessage('usernameOutput', [this.org.getUsername()])); } - const waitFlag = this.getFlag('wait'); + const waitFlag = this.flags.wait; const waitDuration = waitFlag.minutes === -1 ? Duration.days(7) : waitFlag; this.isAsync = waitDuration.quantity === 0; - const deployId = this.resolveDeployId(this.getFlag('jobid')); + const deployId = this.resolveDeployId(this.flags.jobid); this.resultsDir = this.resolveOutputDir( - this.getFlag('coverageformatters', undefined), - this.getFlag('junit'), - this.getFlag('resultsdir'), + this.flags.coverageformatters, + this.flags.junit, + this.flags.resultsdir, deployId, false ); if (this.isAsync) { - this.deployResult = await this.report(deployId); + this.deployResult = await this.report(this.org.getConnection(), deployId); return; } - const deploy = this.createDeploy(deployId); - if (!this.isJsonOutput()) { + const deploy = this.createDeploy(this.org.getConnection(), deployId); + if (!this.jsonEnabled()) { const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux); + ? new DeployProgressBarFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })) + : new DeployProgressStatusFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })); progressFormatter.progress(deploy); } @@ -99,8 +120,8 @@ export class Report extends DeployCommand { this.deployResult = await deploy.pollStatus({ frequency: Duration.milliseconds(500), timeout: waitDuration }); } catch (error) { if (error instanceof Error && error.message.includes('The client has timed out')) { - this.logger.debug('mdapi:deploy:report polling timed out. Requesting status...'); - this.deployResult = await this.report(deployId); + this.debug('mdapi:deploy:report polling timed out. Requesting status...'); + this.deployResult = await this.report(this.org.getConnection(), deployId); } else { throw error; } @@ -124,23 +145,26 @@ export class Report extends DeployCommand { protected formatResult(): MdDeployResult { const formatter = new MdDeployResultFormatter( - this.logger, - this.ux, + new Ux({ jsonEnabled: this.jsonEnabled() }), { - concise: this.getFlag('concise', false), - verbose: this.getFlag('verbose', false), - coverageOptions: getCoverageFormattersOptions(this.getFlag('coverageformatters', undefined)), - junitTestResults: this.getFlag('junit', false), + concise: this.flags.concise ?? false, + verbose: this.flags.verbose ?? false, + coverageOptions: getCoverageFormattersOptions(this.flags.coverageformatters), + junitTestResults: this.flags.junit ?? false, resultsDir: this.resultsDir, testsRan: !!this.deployResult?.response?.numberTestsTotal, }, this.deployResult ); - this.maybeCreateRequestedReports(); + this.maybeCreateRequestedReports({ + coverageformatters: this.flags.coverageformatters, + junit: this.flags.junit, + org: this.org, + }); // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(true); } diff --git a/src/commands/force/mdapi/retrieve.ts b/src/commands/force/mdapi/retrieve.ts index 39aebdc3f..ced2c2293 100644 --- a/src/commands/force/mdapi/retrieve.ts +++ b/src/commands/force/mdapi/retrieve.ts @@ -4,10 +4,7 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ - -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages, SfError, SfProject } from '@salesforce/core'; +import { Lifecycle, Messages, Org, SfError, SfProject } from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { ComponentSetBuilder, @@ -17,6 +14,14 @@ import { RetrieveVersionData, } from '@salesforce/source-deploy-retrieve'; import { Optional } from '@salesforce/ts-types'; +import { + arrayWithDeprecation, + Flags, + loglevel, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { resolveZipFileName, SourceCommand } from '../../../sourceCommand'; import { Stash } from '../../../stash'; import { @@ -28,69 +33,70 @@ import { Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.retrieve'); const spinnerMessages = Messages.loadMessages('@salesforce/plugin-source', 'spinner'); -const retrieveMessages = Messages.load('@salesforce/plugin-source', 'retrieve', ['apiVersionMsgDetailed']); +const retrieveMessages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); +export type RetrieveCommandCombinedResult = RetrieveCommandResult | RetrieveCommandAsyncResult; +const replacement = 'project retrieve start'; export class Retrieve extends SourceCommand { - public static aliases = ['force:mdapi:beta:retrieve']; - public static readonly description = messages.getMessage('retrieveCmd.description'); - public static readonly examples = messages.getMessage('retrieveCmd.examples').split(os.EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - retrievetargetdir: flags.directory({ + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly summary = messages.getMessage('retrieve.summary'); + public static readonly description = messages.getMessage('retrieve.description'); + public static readonly examples = messages.getMessages('retrieve.examples'); + public static readonly flags = { + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + retrievetargetdir: Flags.directory({ char: 'r', - description: messages.getMessage('flags.retrievetargetdir'), - longDescription: messages.getMessage('flagsLong.retrievetargetdir'), + summary: messages.getMessage('flags.retrievetargetdir.summary'), required: true, }), - unpackaged: flags.filepath({ + unpackaged: Flags.file({ char: 'k', - description: messages.getMessage('flags.unpackaged'), - longDescription: messages.getMessage('flagsLong.unpackaged'), + summary: messages.getMessage('flags.unpackaged.summary'), exclusive: ['sourcedir', 'packagenames'], }), - sourcedir: flags.directory({ + sourcedir: Flags.directory({ char: 'd', - description: messages.getMessage('flags.sourcedir'), - longDescription: messages.getMessage('flagsLong.sourcedir'), + summary: messages.getMessage('flags.sourcedir.summary'), exclusive: ['unpackaged', 'packagenames'], }), - packagenames: flags.array({ + packagenames: arrayWithDeprecation({ char: 'p', - description: messages.getMessage('flags.packagenames'), - longDescription: messages.getMessage('flagsLong.packagenames'), + summary: messages.getMessage('flags.packagenames.summary'), exclusive: ['sourcedir', 'unpackaged'], }), - singlepackage: flags.boolean({ + singlepackage: Flags.boolean({ char: 's', - description: messages.getMessage('flags.singlepackage'), - longDescription: messages.getMessage('flagsLong.singlepackage'), + description: messages.getMessage('flags.singlepackage.description'), + summary: messages.getMessage('flags.singlepackage.summary'), }), - zipfilename: flags.string({ + zipfilename: Flags.string({ char: 'n', - description: messages.getMessage('flags.zipfilename'), - longDescription: messages.getMessage('flagsLong.zipfilename'), + summary: messages.getMessage('flags.zipfilename.summary'), }), - unzip: flags.boolean({ + unzip: Flags.boolean({ char: 'z', - description: messages.getMessage('flags.unzip'), - longDescription: messages.getMessage('flagsLong.unzip'), + summary: messages.getMessage('flags.unzip.summary'), }), - wait: flags.minutes({ + wait: Flags.duration({ char: 'w', - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + unit: 'minutes', + summary: messages.getMessage('flags.wait.summary'), default: Duration.minutes(1440), // 24 hours is a reasonable default versus -1 (no timeout) }), - apiversion: flags.builtin({ + apiversion: Flags.string({ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore force char override for backward compat char: 'a', - description: messages.getMessage('flags.apiversion'), - longDescription: messages.getMessage('flagsLong.apiversion'), + description: messages.getMessage('flags.apiversion.description'), + summary: messages.getMessage('flags.apiversion.summary'), }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), - longDescription: messages.getMessage('flagsLong.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), }; @@ -102,24 +108,27 @@ export class Retrieve extends SourceCommand { private wait: Duration; private isAsync: boolean; private mdapiRetrieve: MetadataApiRetrieve; - - public async run(): Promise { + private flags: Interfaces.InferredFlags; + private org: Org; + public async run(): Promise { + this.flags = (await this.parse(Retrieve)).flags; + this.org = this.flags['target-org']; await this.retrieve(); this.resolveSuccess(); return this.formatResult(); } protected async retrieve(): Promise { - const packagenames = this.getFlag('packagenames'); + const packagenames = this.flags.packagenames; if (!packagenames && !this.flags.unpackaged) { - this.sourceDir = this.resolveRootDir(this.getFlag('sourcedir')); + this.sourceDir = this.resolveRootDir(this.flags.sourcedir); } - this.retrieveTargetDir = this.resolveOutputDir(this.getFlag('retrievetargetdir')); - const manifest = this.resolveManifest(this.getFlag('unpackaged')); - const singlePackage = this.getFlag('singlepackage'); - this.zipFileName = resolveZipFileName(this.getFlag('zipfilename')); - this.unzip = this.getFlag('unzip'); - const waitFlag = this.getFlag('wait'); + this.retrieveTargetDir = this.resolveOutputDir(this.flags.retrievetargetdir); + const manifest = this.resolveManifest(this.flags.unpackaged); + const singlePackage = this.flags.singlepackage; + this.zipFileName = resolveZipFileName(this.flags.zipfilename); + this.unzip = this.flags.unzip; + const waitFlag = this.flags.wait; this.wait = waitFlag.minutes === -1 ? Duration.days(7) : waitFlag; this.isAsync = this.wait.quantity === 0; @@ -127,14 +136,14 @@ export class Retrieve extends SourceCommand { throw new SfError(messages.getMessage('InvalidPackageNames', [packagenames.toString()]), 'InvalidPackageNames'); } - this.ux.startSpinner(spinnerMessages.getMessage('retrieve.main', [this.org.getUsername()])); - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.componentSetBuild')); + this.spinner.start(spinnerMessages.getMessage('retrieve.main', [this.org.getUsername()])); + this.spinner.status = spinnerMessages.getMessage('retrieve.componentSetBuild'); this.componentSet = await ComponentSetBuilder.build({ // use the apiVersion if provided. // Manifests default to their specified apiVersion(ComponentSetBuilder handles this) // and not specifying the apiVersion will use the max for the org/Connection - apiversion: this.getFlag('apiversion'), + apiversion: this.flags.apiversion, packagenames, sourcepath: this.sourceDir ? [this.sourceDir] : undefined, manifest: manifest && { @@ -143,11 +152,11 @@ export class Retrieve extends SourceCommand { }, }); - await this.lifecycle.emit('preretrieve', { packageXmlPath: manifest }); + await Lifecycle.getInstance().emit('preretrieve', { packageXmlPath: manifest }); const username = this.org.getUsername(); // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { - this.ux.log( + Lifecycle.getInstance().on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { + this.log( retrieveMessages.getMessage('apiVersionMsgDetailed', [ 'Retrieving', apiData.manifestVersion, @@ -156,12 +165,12 @@ export class Retrieve extends SourceCommand { ]) ); }); - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.sendingRequest')); + this.spinner.status = spinnerMessages.getMessage('retrieve.sendingRequest'); this.mdapiRetrieve = await this.componentSet.retrieve({ usernameOrConnection: username, output: this.retrieveTargetDir, - packageOptions: this.getFlag('packagenames'), + packageOptions: this.flags.packagenames, format: 'metadata', singlePackage, zipFileName: this.zipFileName, @@ -175,17 +184,17 @@ export class Retrieve extends SourceCommand { unzip: this.unzip, }); - this.ux.log(`Retrieve ID: ${this.mdapiRetrieve.id}`); + this.log(`Retrieve ID: ${this.mdapiRetrieve.id}`); if (this.isAsync) { - this.ux.stopSpinner('queued'); + this.spinner.stop('queued'); } else { - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.polling')); + this.spinner.status = spinnerMessages.getMessage('retrieve.polling'); this.retrieveResult = await this.mdapiRetrieve.pollStatus({ frequency: Duration.milliseconds(1000), timeout: this.wait, }); - this.ux.stopSpinner(); + this.spinner.stop(); } } @@ -207,12 +216,12 @@ export class Retrieve extends SourceCommand { // async result if (this.isAsync) { let cmdFlags = `--jobid ${this.mdapiRetrieve.id} --retrievetargetdir ${this.retrieveTargetDir}`; - const targetusernameFlag = this.getFlag('targetusername'); + const targetusernameFlag = this.flags['target-org']; if (targetusernameFlag) { - cmdFlags += ` --targetusername ${targetusernameFlag}`; + cmdFlags += ` --targetusername ${targetusernameFlag.getUsername()}`; } - this.ux.log(''); - this.ux.log(messages.getMessage('checkStatus', [cmdFlags])); + this.log(''); + this.log(messages.getMessage('checkStatus', [cmdFlags])); return { done: false, id: this.mdapiRetrieve.id, @@ -223,14 +232,18 @@ export class Retrieve extends SourceCommand { } else { const formatterOptions = { waitTime: this.wait.quantity, - verbose: this.getFlag('verbose', false), + verbose: this.flags.verbose ?? false, retrieveTargetDir: this.retrieveTargetDir, zipFileName: this.zipFileName, unzip: this.unzip, }; - const formatter = new RetrieveResultFormatter(this.logger, this.ux, formatterOptions, this.retrieveResult); + const formatter = new RetrieveResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.retrieveResult + ); - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } return formatter.getJson(); @@ -241,7 +254,7 @@ export class Retrieve extends SourceCommand { try { return SfProject.getInstance().getDefaultPackage().fullPath; } catch (error) { - this.logger.debug('No SFDX project found for default package directory'); + this.debug('No SFDX project found for default package directory'); } } diff --git a/src/commands/force/mdapi/retrieve/report.ts b/src/commands/force/mdapi/retrieve/report.ts index d2a991984..65db06465 100644 --- a/src/commands/force/mdapi/retrieve/report.ts +++ b/src/commands/force/mdapi/retrieve/report.ts @@ -4,12 +4,17 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ - -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages, SfError } from '@salesforce/core'; +import { Messages, Org, SfError } from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { MetadataApiRetrieve, MetadataApiRetrieveStatus, RetrieveResult } from '@salesforce/source-deploy-retrieve'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { resolveZipFileName, SourceCommand } from '../../../../sourceCommand'; import { Stash, MdRetrieveData } from '../../../../stash'; import { @@ -21,45 +26,44 @@ import { Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.retrieve'); const spinnerMessages = Messages.loadMessages('@salesforce/plugin-source', 'spinner'); - +export type ReportCommandResult = RetrieveCommandResult | RetrieveCommandAsyncResult; export class Report extends SourceCommand { - public static aliases = ['force:mdapi:beta:retrieve:report']; - public static readonly description = messages.getMessage('reportCmd.description'); - public static readonly examples = messages.getMessage('reportCmd.examples').split(os.EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { + public static readonly summary = messages.getMessage('report.summary'); + public static readonly description = messages.getMessage('report.description'); + public static readonly examples = messages.getMessages('report.examples'); + public static readonly state = 'deprecated'; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, // NOTE: this flag is not required because the value is stashed // from the force:mdapi:retrieve command. - retrievetargetdir: flags.directory({ + retrievetargetdir: Flags.directory({ char: 'r', - description: messages.getMessage('flags.retrievetargetdir'), - longDescription: messages.getMessage('flagsLong.retrievetargetdir'), + summary: messages.getMessage('flags.retrievetargetdir.summary'), }), - jobid: flags.id({ + jobid: Flags.salesforceId({ char: 'i', - description: messages.getMessage('flags.jobid'), - longDescription: messages.getMessage('flagsLong.jobid'), + description: messages.getMessage('flags.jobid.description'), + summary: messages.getMessage('flags.jobid.summary'), }), - zipfilename: flags.string({ + zipfilename: Flags.string({ char: 'n', - description: messages.getMessage('flags.zipfilename'), - longDescription: messages.getMessage('flagsLong.zipfilename'), + summary: messages.getMessage('flags.zipfilename.summary'), }), - unzip: flags.boolean({ + unzip: Flags.boolean({ char: 'z', - description: messages.getMessage('flags.unzip'), - longDescription: messages.getMessage('flagsLong.unzip'), + summary: messages.getMessage('flags.unzip.summary'), }), - wait: flags.minutes({ + wait: Flags.duration({ char: 'w', - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + unit: 'minutes', + summary: messages.getMessage('flags.wait.summary'), min: -1, - default: Duration.minutes(1440), // 24 hours is a reasonable default versus -1 (no timeout) + defaultValue: 1440, // 24 hours is a reasonable default versus -1 (no timeout) }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), - longDescription: messages.getMessage('flagsLong.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), }; @@ -71,15 +75,20 @@ export class Report extends SourceCommand { private wait: Duration; private isAsync: boolean; private mdapiRetrieve: MetadataApiRetrieve; + private flags: Interfaces.InferredFlags; + private org: Org; + + public async run(): Promise { + this.flags = (await this.parse(Report)).flags; + this.org = this.flags['target-org']; - public async run(): Promise { await this.report(); this.resolveSuccess(); return this.formatResult(); } protected async report(): Promise { - let retrieveId = this.getFlag('jobid'); + let retrieveId = this.flags.jobid; if (!retrieveId) { // Get stashed retrieve data @@ -94,17 +103,17 @@ export class Report extends SourceCommand { this.zipFileName = resolveZipFileName(mdRetrieveStash?.zipfilename); this.unzip = mdRetrieveStash?.unzip; } else { - this.retrieveTargetDir = this.resolveOutputDir(this.getFlag('retrievetargetdir')); - this.zipFileName = resolveZipFileName(this.getFlag('zipfilename')); - this.unzip = this.getFlag('unzip'); + this.retrieveTargetDir = this.resolveOutputDir(this.flags.retrievetargetdir); + this.zipFileName = resolveZipFileName(this.flags.zipfilename); + this.unzip = this.flags.unzip; } - const waitFlag = this.getFlag('wait'); + const waitFlag = this.flags.wait; this.wait = waitFlag.minutes === -1 ? Duration.days(7) : waitFlag; this.isAsync = this.wait.quantity === 0; - this.ux.startSpinner(spinnerMessages.getMessage('retrieve.main', [this.org.getUsername()])); + this.spinner.start(spinnerMessages.getMessage('retrieve.main', [this.org.getUsername()])); this.mdapiRetrieve = new MetadataApiRetrieve({ id: retrieveId, @@ -123,11 +132,11 @@ export class Report extends SourceCommand { this.retrieveResult = await this.mdapiRetrieve.post(this.retrieveStatus); } } else { - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.polling')); + this.spinner.status = spinnerMessages.getMessage('retrieve.polling'); this.retrieveResult = await this.mdapiRetrieve.pollStatus(1000, this.wait.seconds); } - this.ux.stopSpinner(); + this.spinner.stop(); } // No-op implementation since any RetrieveResult status would be a success. @@ -139,8 +148,8 @@ export class Report extends SourceCommand { protected formatResult(): RetrieveCommandResult | RetrieveCommandAsyncResult { if (this.isAsync && !this.retrieveResult) { - this.ux.log(''); - this.ux.log(`Retrieve Status: ${this.retrieveStatus.status}`); + this.log(''); + this.log(`Retrieve Status: ${this.retrieveStatus.status}`); return { done: this.retrieveStatus.done, id: this.retrieveStatus.id, @@ -152,14 +161,18 @@ export class Report extends SourceCommand { const formatterOptions = { waitTime: this.wait.quantity, - verbose: this.getFlag('verbose', false), + verbose: this.flags.verbose ?? false, retrieveTargetDir: this.retrieveTargetDir, zipFileName: this.zipFileName, unzip: this.unzip, }; - const formatter = new RetrieveResultFormatter(this.logger, this.ux, formatterOptions, this.retrieveResult); + const formatter = new RetrieveResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.retrieveResult + ); - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } return formatter.getJson(); diff --git a/src/commands/force/source/convert.ts b/src/commands/force/source/convert.ts deleted file mode 100644 index e7dacb335..000000000 --- a/src/commands/force/source/convert.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as os from 'os'; -import { join, resolve } from 'path'; -import * as fs from 'fs'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import { ComponentSetBuilder, ConvertResult, MetadataConverter } from '@salesforce/source-deploy-retrieve'; -import { getString } from '@salesforce/ts-types'; -import { SourceCommand } from '../../../sourceCommand'; -import { ConvertCommandResult, ConvertResultFormatter } from '../../../formatters/convertResultFormatter'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'convert'); - -export class Convert extends SourceCommand { - public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresProject = true; - public static readonly flagsConfig: FlagsConfig = { - rootdir: flags.directory({ - char: 'r', - description: messages.getMessage('flags.rootdir'), - }), - outputdir: flags.directory({ - default: `metadataPackage_${Date.now()}`, - char: 'd', - description: messages.getMessage('flags.outputdir'), - }), - packagename: flags.string({ - char: 'n', - description: messages.getMessage('flags.packagename'), - }), - manifest: flags.string({ - char: 'x', - description: messages.getMessage('flags.manifest'), - longDescription: messages.getMessage('flagsLong.manifest'), - }), - sourcepath: flags.array({ - char: 'p', - description: messages.getMessage('flags.sourcepath'), - longDescription: messages.getMessage('flagsLong.sourcepath'), - exclusive: ['manifest', 'metadata'], - }), - metadata: flags.array({ - char: 'm', - description: messages.getMessage('flags.metadata'), - exclusive: ['manifest', 'sourcepath'], - }), - }; - - protected convertResult: ConvertResult; - - public async run(): Promise { - await this.convert(); - this.resolveSuccess(); - return this.formatResult(); - } - - protected async convert(): Promise { - const paths: string[] = []; - - const { sourcepath, metadata, manifest, rootdir } = this.flags; - - if (sourcepath) { - paths.push(...(sourcepath as string[])); - } - - // rootdir behaves exclusively to sourcepath, metadata, and manifest... to maintain backwards compatibility - // we will check here, instead of adding the exclusive option to the flag definition so we don't break scripts - if (rootdir && !sourcepath && !metadata && !manifest && typeof rootdir === 'string') { - // only rootdir option passed - paths.push(rootdir); - } - - // no options passed, convert the default package (usually force-app) - if (!sourcepath && !metadata && !manifest && !rootdir) { - paths.push(this.project.getDefaultPackage().path); - } - - this.componentSet = await ComponentSetBuilder.build({ - sourceapiversion: await this.getSourceApiVersion(), - sourcepath: paths, - manifest: manifest && { - manifestPath: this.getFlag('manifest'), - directoryPaths: this.getPackageDirs(), - }, - metadata: metadata && { - metadataEntries: this.getFlag('metadata'), - directoryPaths: this.getPackageDirs(), - }, - }); - - const packageName = this.getFlag('packagename'); - const outputDirectory = resolve(this.getFlag('outputdir')); - const converter = new MetadataConverter(); - this.convertResult = await converter.convert(this.componentSet, 'metadata', { - type: 'directory', - outputDirectory, - packageName, - genUniqueDir: false, - }); - - if (packageName) { - // SDR will build an output path like /output/directory/packageName/package.xml - // this was breaking from toolbelt, so to revert it we copy the directory up a level and delete the original - this.copyDir(this.convertResult.packagePath, outputDirectory); - fs.rmSync(this.convertResult.packagePath, { recursive: true }); - this.convertResult.packagePath = outputDirectory; - } - } - - // TODO: move into fs in sfdx-core - protected copyDir(src: string, dest: string): void { - fs.mkdirSync(dest, { recursive: true }); - const entries = fs.readdirSync(src, { withFileTypes: true }); - - entries.map((entry) => { - const srcPath = join(src, entry.name); - const destPath = join(dest, entry.name); - - return entry.isDirectory() ? this.copyDir(srcPath, destPath) : fs.copyFileSync(srcPath, destPath); - }); - } - - protected resolveSuccess(): void { - if (!getString(this.convertResult, 'packagePath')) { - this.setExitCode(1); - } - } - - protected formatResult(): ConvertCommandResult { - const formatter = new ConvertResultFormatter(this.logger, this.ux, this.convertResult); - - if (!this.isJsonOutput()) { - formatter.display(); - } - return formatter.getJson(); - } -} diff --git a/src/commands/force/source/delete.ts b/src/commands/force/source/delete.ts deleted file mode 100644 index cae9a5415..000000000 --- a/src/commands/force/source/delete.ts +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import * as os from 'os'; -import * as fs from 'fs'; -import * as path from 'path'; -import { ux } from '@oclif/core'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import { - ComponentSet, - ComponentSetBuilder, - ComponentStatus, - DestructiveChangesType, - FileResponse, - MetadataComponent, - RequestStatus, - SourceComponent, -} from '@salesforce/source-deploy-retrieve'; -import { Duration, env } from '@salesforce/kit'; -import { SourceTracking } from '@salesforce/source-tracking'; -import { DeployCommand, TestLevel } from '../../../deployCommand'; -import { DeployCommandResult, DeployResultFormatter } from '../../../formatters/deployResultFormatter'; -import { DeleteResultFormatter } from '../../../formatters/source/deleteResultFormatter'; -import { ProgressFormatter } from '../../../formatters/progressFormatter'; -import { DeployProgressBarFormatter } from '../../../formatters/deployProgressBarFormatter'; -import { DeployProgressStatusFormatter } from '../../../formatters/deployProgressStatusFormatter'; -import { filterConflictsByComponentSet, trackingSetup, updateTracking } from '../../../trackingFunctions'; - -const fsPromises = fs.promises; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'delete'); -const xorFlags = ['metadata', 'sourcepath']; -export class Delete extends DeployCommand { - public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresProject = true; - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - checkonly: flags.boolean({ - char: 'c', - description: messages.getMessage('flags.checkonly'), - longDescription: messages.getMessage('flagsLong.checkonly'), - }), - wait: flags.minutes({ - char: 'w', - default: Duration.minutes(Delete.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), - }), - testlevel: flags.enum({ - char: 'l', - description: messages.getMessage('flags.testLevel'), - longDescription: messages.getMessage('flagsLong.testLevel'), - options: ['NoTestRun', 'RunLocalTests', 'RunAllTestsInOrg'], - default: 'NoTestRun', - }), - noprompt: flags.boolean({ - char: 'r', - description: messages.getMessage('flags.noprompt'), - }), - metadata: flags.array({ - char: 'm', - description: messages.getMessage('flags.metadata'), - longDescription: messages.getMessage('flagsLong.metadata'), - exactlyOne: xorFlags, - }), - sourcepath: flags.array({ - char: 'p', - description: messages.getMessage('flags.sourcepath'), - longDescription: messages.getMessage('flagsLong.sourcepath'), - exactlyOne: xorFlags, - }), - tracksource: flags.boolean({ - char: 't', - description: messages.getMessage('flags.tracksource'), - exclusive: ['checkonly'], - }), - forceoverwrite: flags.boolean({ - char: 'f', - description: messages.getMessage('flags.forceoverwrite'), - dependsOn: ['tracksource'], - }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), - }), - }; - protected fileResponses: FileResponse[]; - protected tracking: SourceTracking; - protected readonly lifecycleEventNames = ['predeploy', 'postdeploy']; - private deleteResultFormatter: DeleteResultFormatter | DeployResultFormatter; - private aborted = false; - private components: MetadataComponent[]; - // create the delete FileResponse as we're parsing the comp. set to use in the output - private mixedDeployDelete: { deploy: string[]; delete: FileResponse[] } = { delete: [], deploy: [] }; - // map of component in project, to where it is stashed - private stashPath = new Map(); - private tempDir = path.join(os.tmpdir(), 'source_delete'); - - public async run(): Promise { - await this.preChecks(); - await this.delete(); - - await this.resolveSuccess(); - const result = this.formatResult(); - // The DeleteResultFormatter will use SDR and scan the directory, if the files have been deleted, it will throw an error - // so we'll delete the files locally now - await this.deleteFilesLocally(); - // makes sure files are deleted before updating tracking files - await this.maybeUpdateTracking(); - return result; - } - - protected async preChecks(): Promise { - if (this.getFlag('tracksource')) { - this.tracking = await trackingSetup({ - commandName: 'force:source:delete', - ignoreConflicts: true, - org: this.org, - project: this.project, - ux: this.ux, - }); - } - } - - protected async delete(): Promise { - this.deleteResultFormatter = new DeleteResultFormatter(this.logger, this.ux, {}); - const sourcepaths = this.getFlag('sourcepath'); - - this.componentSet = await ComponentSetBuilder.build({ - apiversion: this.getFlag('apiversion'), - sourceapiversion: await this.getSourceApiVersion(), - sourcepath: sourcepaths, - metadata: this.flags.metadata && { - metadataEntries: this.getFlag('metadata'), - directoryPaths: this.getPackageDirs(), - }, - }); - if (this.getFlag('tracksource') && !this.getFlag('forceoverwrite')) { - await filterConflictsByComponentSet({ tracking: this.tracking, components: this.componentSet, ux: this.ux }); - } - this.components = this.componentSet.toArray(); - - if (!this.components.length) { - // if we didn't find any components to delete, let the user know and exit - (this.deleteResultFormatter as DeleteResultFormatter).displayNoResultsFound(); - return; - } - - // create a new ComponentSet and mark everything for deletion - const cs = new ComponentSet([]); - cs.apiVersion = this.getFlag('apiversion') ?? (await this.org.retrieveMaxApiVersion()); - cs.sourceApiVersion = this.getFlag('apiversion') ?? (await this.getSourceApiVersion()); - this.components.map((component) => { - if (component instanceof SourceComponent) { - cs.add(component, DestructiveChangesType.POST); - } else { - // a remote-only delete - cs.add(new SourceComponent({ name: component.fullName, type: component.type }), DestructiveChangesType.POST); - } - }); - this.componentSet = cs; - - if (sourcepaths) { - // determine if user is trying to delete a single file from a bundle, which is actually just an fs delete operation - // and then a constructive deploy on the "new" bundle - this.components - .filter((comp) => comp.type.strategies?.adapter === 'bundle' && comp instanceof SourceComponent) - .map((bundle: SourceComponent) => { - sourcepaths.map(async (sourcepath) => { - // walkContent returns absolute paths while sourcepath will usually be relative - if (bundle.walkContent().find((content) => content.endsWith(sourcepath))) { - await this.moveBundleToManifest(bundle, sourcepath); - } - }); - }); - } - - this.aborted = !(await this.handlePrompt()); - if (this.aborted) return; - - // fire predeploy event for the delete - await this.lifecycle.emit('predeploy', this.components); - this.isRest = this.isRestDeploy(); - this.ux.log(`*** Deleting with ${this.isRest ? 'REST' : 'SOAP'} API ***`); - - const deploy = await this.componentSet.deploy({ - usernameOrConnection: this.org.getUsername(), - apiOptions: { - rest: this.isRest, - checkOnly: this.getFlag('checkonly', false), - testLevel: this.getFlag('testlevel'), - }, - }); - this.updateDeployId(deploy.id); - - if (!this.isJsonOutput()) { - const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux); - progressFormatter.progress(deploy); - } - - this.deployResult = await deploy.pollStatus({ timeout: this.getFlag('wait') }); - await this.lifecycle.emit('postdeploy', this.deployResult); - - // result.getFileResponses() will crawl the tree, but that would throw after the delete occurs. - // Extract them here for updateTracking to use later - this.fileResponses = this.mixedDeployDelete.delete.length - ? this.mixedDeployDelete.delete - : this.deployResult.getFileResponses(); - } - - /** - * Checks the response status to determine whether the delete was successful. - */ - protected async resolveSuccess(): Promise { - const status = this.deployResult?.response?.status; - if (status !== RequestStatus.Succeeded && !this.aborted) { - this.setExitCode(1); - } - // if deploy failed OR the operation was cancelled, restore the stashed files if they exist - else if (status !== RequestStatus.Succeeded || this.aborted) { - await Promise.all( - this.mixedDeployDelete.delete.map(async (file) => { - await this.restoreFileFromStash(file.filePath); - }) - ); - } else if (this.mixedDeployDelete.delete.length) { - // successful delete -> delete the stashed file - await this.deleteStash(); - } - } - - protected formatResult(): DeployCommandResult { - const formatterOptions = { - verbose: this.getFlag('verbose', false), - }; - - this.deleteResultFormatter = this.mixedDeployDelete.deploy.length - ? new DeployResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult) - : new DeleteResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult); - - // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { - this.deleteResultFormatter.display(); - } - - if (this.mixedDeployDelete.deploy.length && !this.aborted) { - // override JSON output when we actually deployed - const json = this.deleteResultFormatter.getJson(); - json.deletedSource = this.mixedDeployDelete.delete; // to match toolbelt json output - json.outboundFiles = []; // to match toolbelt version - json.deletes = json.deploys; // to match toolbelt version - delete json.deploys; - return json; - } - - if (this.aborted) { - return { - status: 0, - result: { - deletedSource: [], - outboundFiles: [], - deletes: [{}], - }, - } as unknown as DeployCommandResult; - } - - return this.deleteResultFormatter.getJson(); - } - - private async maybeUpdateTracking(): Promise { - if (this.getFlag('tracksource', false)) { - return updateTracking({ - ux: this.ux, - result: this.deployResult, - tracking: this.tracking, - fileResponses: this.fileResponses, - }); - } - } - - private async deleteFilesLocally(): Promise { - if (!this.getFlag('checkonly') && this.deployResult?.response?.status === RequestStatus.Succeeded) { - const promises = []; - this.components.map((component: SourceComponent) => { - // mixed delete/deploy operations have already been deleted and stashed - if (!this.mixedDeployDelete.delete.length) { - if (component.content) { - const stats = fs.statSync(component.content); - if (stats.isDirectory()) { - promises.push(fsPromises.rm(component.content, { recursive: true })); - } else { - promises.push(fsPromises.unlink(component.content)); - } - } - if (component.xml) { - promises.push(fsPromises.unlink(component.xml)); - } - } - }); - await Promise.all(promises); - } - } - - private async moveFileToStash(file: string): Promise { - await fsPromises.mkdir(path.dirname(this.stashPath.get(file)), { recursive: true }); - await fsPromises.copyFile(file, this.stashPath.get(file)); - await fsPromises.unlink(file); - } - - private async restoreFileFromStash(file: string): Promise { - await fsPromises.rename(this.stashPath.get(file), file); - } - - private async deleteStash(): Promise { - await fsPromises.rm(this.tempDir, { recursive: true, force: true }); - } - - private async moveBundleToManifest(bundle: SourceComponent, sourcepath: string): Promise { - // if one of the passed in sourcepaths is to a bundle component - const fileName = path.basename(sourcepath); - const fullName = path.join(bundle.name, fileName); - this.mixedDeployDelete.delete.push({ - state: ComponentStatus.Deleted, - fullName, - type: bundle.type.name, - filePath: sourcepath, - }); - // stash the file in case we need to restore it due to failed deploy/aborted command - this.stashPath.set(sourcepath, path.join(this.tempDir, fullName)); - await this.moveFileToStash(sourcepath); - - // re-walk the directory to avoid picking up the deleted file - this.mixedDeployDelete.deploy.push(...bundle.walkContent()); - - // now remove the bundle from destructive changes and add to manifest - // set the bundle as NOT marked for delete - this.componentSet.destructiveChangesPost.delete(`${bundle.type.id}#${bundle.fullName}`); - bundle.setMarkedForDelete(false); - this.componentSet.add(bundle); - } - - private async handlePrompt(): Promise { - if (!this.getFlag('noprompt')) { - const remote: string[] = []; - let local: string[] = []; - const message: string[] = []; - - this.components.flatMap((component) => { - if (component instanceof SourceComponent) { - local.push(component.xml, ...component.walkContent()); - } else { - // remote only metadata - remote.push(`${component.type.name}:${component.fullName}`); - } - }); - - if (this.mixedDeployDelete.delete.length) { - local = this.mixedDeployDelete.delete.map((fr) => fr.fullName); - } - - if (this.mixedDeployDelete.deploy.length) { - message.push(messages.getMessage('deployPrompt', [[...new Set(this.mixedDeployDelete.deploy)].join('\n')])); - } - - if (remote.length) { - message.push(messages.getMessage('remotePrompt', [[...new Set(remote)].join('\n')])); - } - - if (local.length) { - if (message.length) { - // add a whitespace between remote and local - message.push('\n'); - } - message.push('\n', messages.getMessage('localPrompt', [[...new Set(local)].join('\n')])); - } - - message.push( - this.getFlag('checkonly', false) - ? messages.getMessage('areYouSureCheckOnly') - : messages.getMessage('areYouSure') - ); - return ux.confirm(message.join('')); - } - return true; - } -} diff --git a/src/commands/force/source/deploy.ts b/src/commands/force/source/deploy.ts index 55ab9e126..e9fb19340 100644 --- a/src/commands/force/source/deploy.ts +++ b/src/commands/force/source/deploy.ts @@ -4,12 +4,20 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; + +import { Lifecycle, Messages, Org } from '@salesforce/core'; import { Duration, env } from '@salesforce/kit'; import { SourceTracking } from '@salesforce/source-tracking'; import { ComponentSetBuilder, DeployVersionData } from '@salesforce/source-deploy-retrieve'; +import { + arrayWithDeprecation, + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand, getCoverageFormattersOptions, reportsFormatters, TestLevel } from '../../../deployCommand'; import { DeployCommandResult, DeployResultFormatter } from '../../../formatters/deployResultFormatter'; import { @@ -29,114 +37,129 @@ const deployMessages = Messages.loadMessages('@salesforce/plugin-source', 'deplo // One of these flags must be specified for a valid deploy. const xorFlags = ['manifest', 'metadata', 'sourcepath', 'validateddeployrequestid']; +export type DeployCommandCombinedResult = DeployCommandResult | DeployCommandAsyncResult; + +const replacement = 'project deploy start'; export class Deploy extends DeployCommand { + public static readonly summary = messages.getMessage('summary'); public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; public static readonly requiresProject = true; - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - checkonly: flags.boolean({ + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + checkonly: Flags.boolean({ char: 'c', - description: messages.getMessage('flags.checkonly'), - longDescription: messages.getMessage('flagsLong.checkonly'), + description: messages.getMessage('flags.checkonly.description'), + summary: messages.getMessage('flags.checkonly.summary'), }), - soapdeploy: flags.boolean({ + soapdeploy: Flags.boolean({ default: false, - description: messages.getMessage('flags.soapDeploy'), + summary: messages.getMessage('flags.soapDeploy.summary'), }), - wait: flags.minutes({ + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(Deploy.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(0), // wait=0 means deploy is asynchronous - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + min: 0, // wait=0 means deploy is asynchronous + summary: messages.getMessage('flags.wait.summary'), + description: messages.getMessage('flags.wait.description'), }), - testlevel: flags.enum({ + testlevel: Flags.string({ char: 'l', - description: messages.getMessage('flags.testLevel'), - longDescription: messages.getMessage('flagsLong.testLevel'), + description: messages.getMessage('flags.testLevel.description'), + summary: messages.getMessage('flags.testLevel.summary'), options: ['NoTestRun', 'RunSpecifiedTests', 'RunLocalTests', 'RunAllTestsInOrg'], }), - runtests: flags.array({ + runtests: arrayWithDeprecation({ char: 'r', - description: messages.getMessage('flags.runTests'), - longDescription: messages.getMessage('flagsLong.runTests'), + summary: messages.getMessage('flags.runTests.summary'), }), - ignoreerrors: flags.boolean({ + ignoreerrors: Flags.boolean({ char: 'o', - description: messages.getMessage('flags.ignoreErrors'), - longDescription: messages.getMessage('flagsLong.ignoreErrors'), + description: messages.getMessage('flags.ignoreErrors.description'), + summary: messages.getMessage('flags.ignoreErrors.summary'), }), - ignorewarnings: flags.boolean({ + ignorewarnings: Flags.boolean({ char: 'g', - description: messages.getMessage('flags.ignoreWarnings'), - longDescription: messages.getMessage('flagsLong.ignoreWarnings'), + description: messages.getMessage('flags.ignoreWarnings.description'), + summary: messages.getMessage('flags.ignoreWarnings.summary'), }), - purgeondelete: flags.boolean({ - description: messages.getMessage('flags.purgeOnDelete'), + purgeondelete: Flags.boolean({ + summary: messages.getMessage('flags.purgeOnDelete.summary'), dependsOn: ['manifest'], }), - validateddeployrequestid: flags.id({ + validateddeployrequestid: Flags.salesforceId({ char: 'q', - description: messages.getMessage('flags.validateDeployRequestId'), - longDescription: messages.getMessage('flagsLong.validateDeployRequestId'), + description: messages.getMessage('flags.validateDeployRequestId.description'), + summary: messages.getMessage('flags.validateDeployRequestId.summary'), exactlyOne: xorFlags, exclusive: ['checkonly', 'testlevel', 'runtests', 'tracksource'], - validate: DeployCommand.isValidDeployId, + startsWith: '0Af', }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), - metadata: flags.array({ + metadata: arrayWithDeprecation({ char: 'm', - description: messages.getMessage('flags.metadata'), - longDescription: messages.getMessage('flagsLong.metadata'), + description: messages.getMessage('flags.metadata.description'), + summary: messages.getMessage('flags.metadata.summary'), exactlyOne: xorFlags, }), - sourcepath: flags.array({ + sourcepath: arrayWithDeprecation({ char: 'p', - description: messages.getMessage('flags.sourcePath'), - longDescription: messages.getMessage('flagsLong.sourcePath'), + description: messages.getMessage('flags.sourcePath.description'), + summary: messages.getMessage('flags.sourcePath.summary'), exactlyOne: xorFlags, }), - manifest: flags.filepath({ + manifest: Flags.file({ char: 'x', - description: messages.getMessage('flags.manifest'), - longDescription: messages.getMessage('flagsLong.manifest'), + description: messages.getMessage('flags.manifest.description'), + summary: messages.getMessage('flags.manifest.summary'), exactlyOne: xorFlags, }), - predestructivechanges: flags.filepath({ - description: messages.getMessage('flags.predestructivechanges'), + predestructivechanges: Flags.file({ + summary: messages.getMessage('flags.predestructivechanges.summary'), dependsOn: ['manifest'], }), - postdestructivechanges: flags.filepath({ - description: messages.getMessage('flags.postdestructivechanges'), + postdestructivechanges: Flags.file({ + summary: messages.getMessage('flags.postdestructivechanges.summary'), dependsOn: ['manifest'], }), - tracksource: flags.boolean({ + tracksource: Flags.boolean({ char: 't', - description: messages.getMessage('flags.tracksource'), + description: messages.getMessage('flags.tracksource.description'), + summary: messages.getMessage('flags.tracksource.summary'), exclusive: ['checkonly', 'validateddeployrequestid'], }), - forceoverwrite: flags.boolean({ + forceoverwrite: Flags.boolean({ char: 'f', - description: messages.getMessage('flags.forceoverwrite'), + summary: messages.getMessage('flags.forceoverwrite.summary'), dependsOn: ['tracksource'], }), - resultsdir: flags.directory({ - description: messages.getMessage('flags.resultsDir'), + resultsdir: Flags.directory({ + summary: messages.getMessage('flags.resultsDir.summary'), }), - coverageformatters: flags.array({ - description: messages.getMessage('flags.coverageFormatters'), + coverageformatters: arrayWithDeprecation({ + summary: messages.getMessage('flags.coverageFormatters.summary'), options: reportsFormatters, helpValue: reportsFormatters.join(','), }), - junit: flags.boolean({ description: messages.getMessage('flags.junit') }), + junit: Flags.boolean({ summary: messages.getMessage('flags.junit.summary') }), }; protected readonly lifecycleEventNames = ['predeploy', 'postdeploy']; protected tracking: SourceTracking; - - public async run(): Promise { + private flags: Interfaces.InferredFlags; + private org: Org; + public async run(): Promise { + this.flags = (await this.parse(Deploy)).flags; + this.org = this.flags['target-org']; await this.preChecks(); await this.deploy(); this.resolveSuccess(); @@ -152,7 +175,7 @@ export class Deploy extends DeployCommand { ignoreConflicts: true, org: this.org, project: this.project, - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), }); } } @@ -162,7 +185,7 @@ export class Deploy extends DeployCommand { // 2. asynchronous - deploy metadata and immediately return. // 3. recent validation - deploy metadata that's already been validated by the org protected async deploy(): Promise { - const waitDuration = this.getFlag('wait'); + const waitDuration = this.flags.wait; this.isAsync = waitDuration.quantity === 0; this.isRest = this.isRestDeploy(); @@ -171,27 +194,34 @@ export class Deploy extends DeployCommand { } if (this.flags.validateddeployrequestid) { - this.deployResult = await this.deployRecentValidation(); + this.deployResult = await this.deployRecentValidation( + this.flags.validateddeployrequestid, + this.org.getConnection() + ); } else { this.componentSet = await ComponentSetBuilder.build({ - apiversion: this.getFlag('apiversion'), + apiversion: this.flags['api-version'], sourceapiversion: await this.getSourceApiVersion(), - sourcepath: this.getFlag('sourcepath'), + sourcepath: this.flags.sourcepath, manifest: this.flags.manifest && { - manifestPath: this.getFlag('manifest'), + manifestPath: this.flags.manifest, directoryPaths: this.getPackageDirs(), - destructiveChangesPre: this.getFlag('predestructivechanges'), - destructiveChangesPost: this.getFlag('postdestructivechanges'), + destructiveChangesPre: this.flags.predestructivechanges, + destructiveChangesPost: this.flags.postdestructivechanges, }, metadata: this.flags.metadata && { - metadataEntries: this.getFlag('metadata'), + metadataEntries: this.flags.metadata, directoryPaths: this.getPackageDirs(), }, }); - if (this.getFlag('tracksource')) { + if (this.flags.tracksource) { // will throw if conflicts exist - if (!this.getFlag('forceoverwrite')) { - await filterConflictsByComponentSet({ tracking: this.tracking, components: this.componentSet, ux: this.ux }); + if (!this.flags.forceoverwrite) { + await filterConflictsByComponentSet({ + tracking: this.tracking, + components: this.componentSet, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + }); } const localDeletes = await this.tracking.getChanges({ origin: 'local', @@ -199,15 +229,15 @@ export class Deploy extends DeployCommand { format: 'string', }); if (localDeletes.length) { - this.ux.warn(messages.getMessage('deployWontDelete')); + this.warn(messages.getMessage('deployWontDelete')); } } // fire predeploy event for sync and async deploys - await this.lifecycle.emit('predeploy', this.componentSet.toArray()); + await Lifecycle.getInstance().emit('predeploy', this.componentSet.toArray()); const username = this.org.getUsername(); // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionDeploy', async (apiData: DeployVersionData) => { - this.ux.log( + Lifecycle.getInstance().on('apiVersionDeploy', async (apiData: DeployVersionData) => { + this.log( deployMessages.getMessage('apiVersionMsgDetailed', [ 'Deploying', apiData.manifestVersion, @@ -222,17 +252,17 @@ export class Deploy extends DeployCommand { usernameOrConnection: username, apiOptions: { ...{ - purgeOnDelete: this.getFlag('purgeondelete', false), - ignoreWarnings: this.getFlag('ignorewarnings', false), - rollbackOnError: !this.getFlag('ignoreerrors', false), - checkOnly: this.getFlag('checkonly', false), + purgeOnDelete: this.flags.purgeondelete ?? false, + ignoreWarnings: this.flags.ignorewarnings ?? false, + rollbackOnError: !this.flags.ignoreerrors ?? false, + checkOnly: this.flags.checkonly ?? false, rest: this.isRest, }, // if runTests is defaulted as 'NoTestRun' and deploying to prod, you'll get this error // https://github.com/forcedotcom/cli/issues/1542 // add additional properties conditionally () - ...(this.getFlag('testlevel') ? { testLevel: this.getFlag('testlevel') } : {}), - ...(this.getFlag('runtests') ? { runTests: this.getFlag('runtests') } : {}), + ...(this.flags.testlevel ? { testLevel: this.flags.testlevel as TestLevel } : {}), + ...(this.flags.runtests ? { runTests: this.flags.runtests } : {}), }, }); this.asyncDeployResult = { id: deploy.id }; @@ -240,10 +270,12 @@ export class Deploy extends DeployCommand { if (!this.isAsync) { // we're not print JSON output - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux, { verbose: this.getFlag('verbose') }); + ? new DeployProgressBarFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })) + : new DeployProgressStatusFormatter(new Ux({ jsonEnabled: this.jsonEnabled() }), { + verbose: this.flags.verbose, + }); progressFormatter.progress(deploy); } this.deployResult = await deploy.pollStatus({ timeout: waitDuration }); @@ -252,38 +284,46 @@ export class Deploy extends DeployCommand { if (this.deployResult) { // Only fire the postdeploy event when we have results. I.e., not async. - await this.lifecycle.emit('postdeploy', this.deployResult); + await Lifecycle.getInstance().emit('postdeploy', this.deployResult); } } protected formatResult(): DeployCommandResult | DeployCommandAsyncResult { this.resultsDir = this.resolveOutputDir( - this.getFlag('coverageformatters', undefined), - this.getFlag('junit'), - this.getFlag('resultsdir'), + this.flags.coverageformatters, + this.flags.junit, + this.flags.resultsdir, this.deployResult?.response?.id, false ); const formatterOptions: ResultFormatterOptions = { - verbose: this.getFlag('verbose', false), + verbose: this.flags.verbose ?? false, username: this.org.getUsername(), - coverageOptions: getCoverageFormattersOptions(this.getFlag('coverageformatters', undefined)), - junitTestResults: this.flags.junit as boolean, + coverageOptions: getCoverageFormattersOptions(this.flags.coverageformatters), + junitTestResults: this.flags.junit, resultsDir: this.resultsDir, - testsRan: this.getFlag('testlevel', 'NoTestRun') !== 'NoTestRun', + testsRan: (this.flags.testlevel ?? 'NoTestRun') !== 'NoTestRun', }; const formatter = this.isAsync - ? new DeployAsyncResultFormatter(this.logger, this.ux, formatterOptions, this.asyncDeployResult) - : new DeployResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult); + ? new DeployAsyncResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.asyncDeployResult + ) + : new DeployResultFormatter(new Ux({ jsonEnabled: this.jsonEnabled() }), formatterOptions, this.deployResult); if (!this.isAsync) { - this.maybeCreateRequestedReports(); + this.maybeCreateRequestedReports({ + coverageformatters: this.flags.coverageformatters, + junit: this.flags.junit, + org: this.org, + }); } // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } @@ -291,8 +331,12 @@ export class Deploy extends DeployCommand { } private async maybeUpdateTracking(): Promise { - if (this.getFlag('tracksource', false)) { - return updateTracking({ ux: this.ux, result: this.deployResult, tracking: this.tracking }); + if (this.flags.tracksource ?? false) { + return updateTracking({ + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + result: this.deployResult, + tracking: this.tracking, + }); } } } diff --git a/src/commands/force/source/deploy/cancel.ts b/src/commands/force/source/deploy/cancel.ts index dd747023c..8016b49e5 100644 --- a/src/commands/force/source/deploy/cancel.ts +++ b/src/commands/force/source/deploy/cancel.ts @@ -4,12 +4,17 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ - -import * as os from 'os'; -import { flags, FlagsConfig } from '@salesforce/command'; import { Messages, SfError } from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { RequestStatus } from '@salesforce/source-deploy-retrieve'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand } from '../../../../deployCommand'; import { DeployCancelCommandResult, @@ -19,38 +24,52 @@ import { Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'cancel'); +const replacement = 'project deploy cancel'; export class Cancel extends DeployCommand { + public static readonly summary = messages.getMessage('summary'); public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - wait: flags.minutes({ + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(DeployCommand.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + min: 1, + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), }), - jobid: flags.id({ + jobid: Flags.salesforceId({ char: 'i', - description: messages.getMessage('flags.jobid'), - validate: DeployCommand.isValidDeployId, + summary: messages.getMessage('flags.jobid.summary'), + startsWith: '0Af', }), }; + private flags: Interfaces.InferredFlags; + public async run(): Promise { + this.flags = (await this.parse(Cancel)).flags; await this.cancel(); this.resolveSuccess(); return this.formatResult(); } protected async cancel(): Promise { - const deployId = this.resolveDeployId(this.getFlag('jobid')); + const conn = this.flags['target-org'].getConnection(this.flags['api-version']); + const deployId = this.resolveDeployId(this.flags.jobid); try { - const deploy = this.createDeploy(deployId); + const deploy = this.createDeploy(conn, deployId); await deploy.cancel(); - this.deployResult = await this.poll(deployId); + this.deployResult = await this.poll(conn, deployId); } catch (e) { const err = e as Error; throw new SfError(messages.getMessage('CancelFailed', [err.message]), 'CancelFailed'); @@ -65,8 +84,8 @@ export class Cancel extends DeployCommand { } protected formatResult(): DeployCancelCommandResult { - const formatter = new DeployCancelResultFormatter(this.logger, this.ux, this.deployResult); - if (!this.isJsonOutput()) { + const formatter = new DeployCancelResultFormatter(new Ux({ jsonEnabled: this.jsonEnabled() }), this.deployResult); + if (!this.jsonEnabled()) { formatter.display(); } return formatter.getJson(); diff --git a/src/commands/force/source/deploy/report.ts b/src/commands/force/source/deploy/report.ts index b1ffda6d4..7276f0417 100644 --- a/src/commands/force/source/deploy/report.ts +++ b/src/commands/force/source/deploy/report.ts @@ -5,11 +5,19 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import * as os from 'os'; import { Messages, SfProject } from '@salesforce/core'; -import { flags, FlagsConfig } from '@salesforce/command'; + import { Duration, env } from '@salesforce/kit'; import { ComponentSetBuilder } from '@salesforce/source-deploy-retrieve'; +import { + arrayWithDeprecation, + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand, getCoverageFormattersOptions, reportsFormatters } from '../../../../deployCommand'; import { DeployReportCommandResult, @@ -23,50 +31,63 @@ import { ResultFormatterOptions } from '../../../../formatters/resultFormatter'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'report'); +const replacement = 'project deploy report'; + export class Report extends DeployCommand { public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - wait: flags.minutes({ + public static readonly summary = messages.getMessage('summary'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(DeployCommand.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + min: 1, + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), }), - jobid: flags.id({ + jobid: Flags.salesforceId({ char: 'i', - description: messages.getMessage('flags.jobid'), - longDescription: messages.getMessage('flagsLong.jobid'), - validate: DeployCommand.isValidDeployId, + summary: messages.getMessage('flags.jobid.summary'), + startsWith: '0Af', }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), - resultsdir: flags.directory({ - description: messages.getMessage('flags.resultsDir'), + resultsdir: Flags.directory({ + summary: messages.getMessage('flags.resultsDir.summary'), }), - coverageformatters: flags.array({ - description: messages.getMessage('flags.coverageFormatters'), + coverageformatters: arrayWithDeprecation({ + summary: messages.getMessage('flags.coverageFormatters.summary'), options: reportsFormatters, helpValue: reportsFormatters.join(','), }), - junit: flags.boolean({ description: messages.getMessage('flags.junit') }), + junit: Flags.boolean({ summary: messages.getMessage('flags.junit.summary') }), }; + private flags: Interfaces.InferredFlags; + public async run(): Promise { + this.flags = (await this.parse(Report)).flags; await this.doReport(); this.resolveSuccess(); return this.formatResult(); } protected async doReport(): Promise { - const deployId = this.resolveDeployId(this.getFlag('jobid')); + const deployId = this.resolveDeployId(this.flags.jobid); this.resultsDir = this.resolveOutputDir( - this.getFlag('coverageformatters', undefined), - this.getFlag('junit'), - this.getFlag('resultsdir'), + this.flags.coverageformatters, + this.flags.junit, + this.flags.resultsdir, deployId, false ); @@ -74,7 +95,7 @@ export class Report extends DeployCommand { // If the verbose flag is set, AND the command was executed from within // an SFDX project, we need to build a ComponentSet so we have mapped // source file output. - if (this.getFlag('verbose')) { + if (this.flags.verbose) { let sourcepath: string[]; try { this.project = await SfProject.resolve(); @@ -85,24 +106,24 @@ export class Report extends DeployCommand { this.componentSet = await ComponentSetBuilder.build({ sourcepath }); } - const waitDuration = this.getFlag('wait'); - const deploy = this.createDeploy(deployId); - if (!this.isJsonOutput()) { + const waitDuration = this.flags.wait; + const deploy = this.createDeploy(this.flags['target-org'].getConnection(), deployId); + if (!this.jsonEnabled()) { const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux); + ? new DeployProgressBarFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })) + : new DeployProgressStatusFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })); progressFormatter.progress(deploy); } try { await deploy.pollStatus({ timeout: waitDuration }); } catch (error) { if (error instanceof Error && error.message.includes('The client has timed out')) { - this.logger.debug('source:deploy:report polling timed out. Requesting status...'); + this.debug('source:deploy:report polling timed out. Requesting status...'); } else { throw error; } } finally { - this.deployResult = await this.report(deployId); + this.deployResult = await this.report(this.flags['target-org'].getConnection(), deployId); } } @@ -115,17 +136,25 @@ export class Report extends DeployCommand { protected formatResult(): DeployReportCommandResult { const formatterOptions: ResultFormatterOptions = { - verbose: this.getFlag('verbose', false), - coverageOptions: getCoverageFormattersOptions(this.getFlag('coverageformatters', undefined)), - junitTestResults: this.flags.junit as boolean, + verbose: this.flags.verbose ?? false, + coverageOptions: getCoverageFormattersOptions(this.flags.coverageformatters), + junitTestResults: this.flags.junit, resultsDir: this.resultsDir, testsRan: !!this.deployResult?.response.numberTestsTotal, }; - const formatter = new DeployReportResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult); + const formatter = new DeployReportResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.deployResult + ); - this.maybeCreateRequestedReports(); + this.maybeCreateRequestedReports({ + coverageformatters: this.flags.coverageformatters, + junit: this.flags.junit, + org: this.flags['target-org'], + }); - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } return formatter.getJson() as DeployReportCommandResult; diff --git a/src/commands/force/source/ignored/list.ts b/src/commands/force/source/ignored/list.ts deleted file mode 100644 index 226b8941c..000000000 --- a/src/commands/force/source/ignored/list.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2022, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import * as path from 'path'; -import * as fs from 'fs'; -import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command'; -import { Messages, SfError } from '@salesforce/core'; -import { ForceIgnore } from '@salesforce/source-deploy-retrieve'; -import { FsError } from '../../../../types'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'ignored_list'); - -export type SourceIgnoredResults = { - ignoredFiles: string[]; -}; - -export class SourceIgnoredCommand extends SfdxCommand { - public static readonly description = messages.getMessage('description'); - public static readonly requiresProject = true; - - public static readonly flagsConfig: FlagsConfig = { - sourcepath: flags.filepath({ - char: 'p', - description: messages.getMessage('flags.sourcepath'), - }), - }; - - private forceIgnore: ForceIgnore; - /** - * Outputs all forceignored files from package directories of a project, - * or based on a sourcepath param that points to a specific file or directory. - */ - // eslint-disable-next-line @typescript-eslint/require-await - public async run(): Promise { - try { - this.forceIgnore = ForceIgnore.findAndCreate(this.project.getPath()); - const sourcepaths = this.flags.sourcepath - ? [this.flags.sourcepath as string] - : this.project.getUniquePackageDirectories().map((pDir) => pDir.path); - - const ignoredFiles = (await Promise.all(sourcepaths.map((sp) => this.statIgnored(sp.trim())))).flat(); - - // Command output - if (ignoredFiles.length) { - this.ux.log('Found the following ignored files:'); - ignoredFiles.forEach((filepath) => this.ux.log(filepath)); - } else { - this.ux.log('No ignored files found in paths:'); - sourcepaths.forEach((sp) => this.ux.log(sp)); - } - - return { ignoredFiles }; - } catch (err) { - const error = err as FsError; - if (error.code === 'ENOENT') { - throw new SfError( - messages.getMessage('invalidSourcePath', [this.flags.sourcepath as string]), - 'invalidSourcePath' - ); - } - throw SfError.wrap(error); - } - } - - // Stat the filepath. Test if a file, recurse if a directory. - private async statIgnored(filepath: string): Promise { - const stats = await fs.promises.stat(filepath); - if (stats.isDirectory()) { - return (await Promise.all(await this.findIgnored(filepath))).flat(); - } else { - return this.isIgnored(filepath) ? [filepath] : []; - } - } - - // Recursively search a directory for source files to test. - private async findIgnored(dir: string): Promise>> { - this.logger.debug(`Searching dir: ${dir}`); - return (await fs.promises.readdir(dir)).map((filename) => this.statIgnored(path.join(dir, filename))); - } - - // Test if a source file is denied, adding any ignored files to - // the ignoredFiles array for output. - private isIgnored(filepath: string): boolean { - if (this.forceIgnore.denies(filepath)) { - this.logger.debug(`[DENIED]: ${filepath}`); - return true; - } - this.logger.debug(`[ACCEPTED]: ${filepath}`); - return false; - } -} diff --git a/src/commands/force/source/manifest/create.ts b/src/commands/force/source/manifest/create.ts deleted file mode 100644 index 969fce385..000000000 --- a/src/commands/force/source/manifest/create.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import * as os from 'os'; -import { join } from 'path'; -import * as fs from 'fs'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import { ComponentSetBuilder } from '@salesforce/source-deploy-retrieve'; -import { SourceCommand } from '../../../../sourceCommand'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'create'); - -const manifestTypes: Record = { - pre: 'destructiveChangesPre.xml', - post: 'destructiveChangesPost.xml', - destroy: 'destructiveChanges.xml', - package: 'package.xml', -}; - -const packageTypes: Record = { - managed: ['beta', 'deleted', 'deprecated', 'installed', 'released'], - unlocked: ['deprecatedEditable', 'installedEditable'], -}; - -interface CreateCommandResult { - name: string; - path: string; -} - -const xorFlags = ['metadata', 'sourcepath', 'fromorg']; -export class create extends SourceCommand { - public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - public static readonly requiresProject = true; - public static readonly flagsConfig: FlagsConfig = { - apiversion: flags.builtin({}), - metadata: flags.array({ - char: 'm', - description: messages.getMessage('flags.metadata'), - exactlyOne: xorFlags, - }), - sourcepath: flags.array({ - char: 'p', - description: messages.getMessage('flags.sourcepath'), - exactlyOne: xorFlags, - }), - manifestname: flags.string({ - char: 'n', - description: messages.getMessage('flags.manifestname'), - exclusive: ['manifesttype'], - }), - manifesttype: flags.enum({ - description: messages.getMessage('flags.manifesttype'), - options: Object.keys(manifestTypes), - char: 't', - }), - includepackages: flags.array({ - description: messages.getMessage('flags.includepackages'), - options: Object.keys(packageTypes), - char: 'c', - dependsOn: ['fromorg'], - }), - fromorg: flags.string({ - description: messages.getMessage('flags.fromorg'), - exactlyOne: xorFlags, - }), - outputdir: flags.string({ - char: 'o', - description: messages.getMessage('flags.outputdir'), - }), - }; - private manifestName: string; - private outputDir: string; - private outputPath: string; - private includepackages: string[]; - - public async run(): Promise { - await this.createManifest(); - this.resolveSuccess(); - return this.formatResult(); - } - - protected async createManifest(): Promise { - // convert the manifesttype into one of the "official" manifest names - // if no manifesttype flag passed, use the manifestname flag - // if no manifestname flag, default to 'package.xml' - this.manifestName = - manifestTypes[this.getFlag('manifesttype')] || this.getFlag('manifestname') || 'package.xml'; - this.outputDir = this.getFlag('outputdir'); - this.includepackages = this.getFlag('includepackages'); - - let exclude: string[] = []; - if (this.includepackages) { - Object.keys(packageTypes).forEach( - (type) => (exclude = !this.includepackages.includes(type) ? exclude.concat(packageTypes[type]) : exclude) - ); - } else { - exclude = Object.values(packageTypes).flat(); - } - - const componentSet = await ComponentSetBuilder.build({ - apiversion: this.getFlag('apiversion') ?? (await this.getSourceApiVersion()), - sourcepath: this.getFlag('sourcepath'), - metadata: this.flags.metadata && { - metadataEntries: this.getFlag('metadata'), - directoryPaths: this.getPackageDirs(), - }, - org: this.flags.fromorg && { - username: this.getFlag('fromorg'), - exclude, - }, - }); - - // add the .xml suffix if the user just provided a file name - this.manifestName = this.manifestName.endsWith('.xml') ? this.manifestName : this.manifestName + '.xml'; - - if (this.outputDir) { - await fs.promises.mkdir(this.outputDir, { recursive: true }); - this.outputPath = join(this.outputDir, this.manifestName); - } else { - this.outputPath = this.manifestName; - } - - return fs.promises.writeFile(this.outputPath, await componentSet.getPackageXml()); - } - - // noop this method because any errors will be reported by the createManifest method - // eslint-disable-next-line @typescript-eslint/no-empty-function, class-methods-use-this - protected resolveSuccess(): void {} - - protected formatResult(): CreateCommandResult { - if (!this.isJsonOutput()) { - if (this.outputDir) { - this.ux.log(messages.getMessage('successOutputDir', [this.manifestName, this.outputDir])); - } else { - this.ux.log(messages.getMessage('success', [this.manifestName])); - } - } - return { path: this.outputPath, name: this.manifestName }; - } -} diff --git a/src/commands/force/source/pull.ts b/src/commands/force/source/pull.ts index 3c02380a4..cf2d87537 100644 --- a/src/commands/force/source/pull.ts +++ b/src/commands/force/source/pull.ts @@ -5,84 +5,97 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { flags, FlagsConfig } from '@salesforce/command'; import { Duration } from '@salesforce/kit'; -import { Messages } from '@salesforce/core'; -import { - FileResponse, - RequestStatus, - RetrieveVersionData, - RetrieveResult, - SourceComponent, -} from '@salesforce/source-deploy-retrieve'; +import { Lifecycle, Messages } from '@salesforce/core'; +import { FileResponse, RequestStatus, RetrieveVersionData, RetrieveResult } from '@salesforce/source-deploy-retrieve'; import { SourceTracking } from '@salesforce/source-tracking'; +import { Interfaces } from '@oclif/core'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; import { SourceCommand } from '../../../sourceCommand'; import { PullResponse, PullResultFormatter } from '../../../formatters/source/pullFormatter'; import { trackingSetup, updateTracking } from '../../../trackingFunctions'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'pull', [ - 'flags.forceoverwrite', - 'description', - 'help', - 'flags.waitLong', -]); -const retrieveMessages = Messages.load('@salesforce/plugin-source', 'retrieve', ['apiVersionMsgDetailed']); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'pull'); +const retrieveMessages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); + +const replacement = 'project retrieve start'; export default class Pull extends SourceCommand { - public static aliases = ['force:source:beta:pull']; + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; public static description = messages.getMessage('description'); - public static help = messages.getMessage('help'); - protected static readonly flagsConfig: FlagsConfig = { - forceoverwrite: flags.boolean({ + public static summary = messages.getMessage('summary'); + public static examples = messages.getMessages('examples'); + public static readonly flags = { + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), + }), + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + forceoverwrite: Flags.boolean({ char: 'f', - description: messages.getMessage('flags.forceoverwrite'), + summary: messages.getMessage('flags.forceoverwrite.summary'), }), // TODO: use shared flags from plugin-source - wait: flags.minutes({ + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(33), - min: Duration.minutes(0), // wait=0 means deploy is asynchronous - description: messages.getMessage('flags.waitLong'), + min: 0, // wait=0 means deploy is asynchronous + summary: messages.getMessage('flags.wait.summary'), + description: messages.getMessage('flags.wait.description'), }), }; - protected static requiresUsername = true; - protected static requiresProject = true; + public static requiresProject = true; protected readonly lifecycleEventNames = ['preretrieve', 'postretrieve']; protected tracking: SourceTracking; protected retrieveResult: RetrieveResult; protected deleteFileResponses: FileResponse[]; + private flags: Interfaces.InferredFlags; public async run(): Promise { + this.flags = (await this.parse(Pull)).flags; + await this.preChecks(); await this.retrieve(); // do not parallelize delete and retrieve...we only get to delete IF retrieve was successful await this.doDeletes(); // deletes includes its tracking file operations await updateTracking({ result: this.retrieveResult, - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), tracking: this.tracking, }); - this.ux.stopSpinner(); + this.spinner.stop(); return this.formatResult(); } protected async preChecks(): Promise { - this.ux.startSpinner('Loading source tracking information'); + this.spinner.start('Loading source tracking information'); this.tracking = await trackingSetup({ commandName: 'force:source:pull', - ignoreConflicts: this.getFlag('forceoverwrite', false), - org: this.org, + ignoreConflicts: this.flags.forceoverwrite ?? false, + org: this.flags['target-org'], project: this.project, - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), }); } protected async doDeletes(): Promise { - this.ux.setSpinnerStatus('Checking for deletes from the org and updating source tracking files'); - const changesToDelete = await this.tracking.getChanges({ + this.spinner.status = 'Checking for deletes from the org and updating source tracking files'; + const changesToDelete = await this.tracking.getChanges({ origin: 'remote', state: 'delete', format: 'SourceComponent', @@ -93,18 +106,18 @@ export default class Pull extends SourceCommand { protected async retrieve(): Promise { const componentSet = await this.tracking.remoteNonDeletesAsComponentSet(); - // if it is't local, add it as a + // if it isn't local, add it as a if (componentSet.size === 0) { return; } componentSet.sourceApiVersion = await this.getSourceApiVersion(); - if (this.getFlag('apiversion')) { - componentSet.apiVersion = this.getFlag('apiversion'); + if (this.flags['api-version']) { + componentSet.apiVersion = this.flags['api-version']; } - const username = this.org.getUsername(); + const username = this.flags['target-org'].getUsername(); // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { - this.ux.log( + Lifecycle.getInstance().on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { + this.log( retrieveMessages.getMessage('apiVersionMsgDetailed', [ 'Pulling', apiData.manifestVersion, @@ -120,14 +133,14 @@ export default class Pull extends SourceCommand { output: this.project.getDefaultPackage().fullPath, }); - this.ux.setSpinnerStatus('Retrieving metadata from the org'); + this.spinner.status = 'Retrieving metadata from the org'; // assume: remote deletes that get deleted locally don't fire hooks? - await this.lifecycle.emit('preretrieve', componentSet.toArray()); - this.retrieveResult = await mdapiRetrieve.pollStatus({ timeout: this.getFlag('wait') }); + await Lifecycle.getInstance().emit('preretrieve', componentSet.toArray()); + this.retrieveResult = await mdapiRetrieve.pollStatus({ timeout: this.flags.wait }); // Assume: remote deletes that get deleted locally don't fire hooks. - await this.lifecycle.emit('postretrieve', this.retrieveResult.getFileResponses()); + await Lifecycle.getInstance().emit('postretrieve', this.retrieveResult.getFileResponses()); } protected resolveSuccess(): void { @@ -146,20 +159,15 @@ export default class Pull extends SourceCommand { } protected formatResult(): PullResponse { - const formatterOptions = { - verbose: this.getFlag('verbose', false), - }; - const formatter = new PullResultFormatter( - this.logger, - this.ux, - formatterOptions, + new Ux({ jsonEnabled: this.jsonEnabled() }), + { verbose: this.flags.verbose ?? false }, this.retrieveResult, this.deleteFileResponses ); // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } diff --git a/src/commands/force/source/push.ts b/src/commands/force/source/push.ts index f77a9c4ae..7112b1d6c 100644 --- a/src/commands/force/source/push.ts +++ b/src/commands/force/source/push.ts @@ -5,12 +5,20 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { flags, FlagsConfig } from '@salesforce/command'; import { Duration, env } from '@salesforce/kit'; -import { Messages } from '@salesforce/core'; +import { Lifecycle, Messages, SfError } from '@salesforce/core'; import { DeployResult, DeployVersionData, RequestStatus } from '@salesforce/source-deploy-retrieve'; import { SourceTracking } from '@salesforce/source-tracking'; import { getBoolean } from '@salesforce/ts-types'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + SfCommand, + Ux, +} from '@salesforce/sf-plugins-core'; +import { Interfaces } from '@oclif/core'; import { DeployCommand } from '../../../deployCommand'; import { PushResponse, PushResultFormatter } from '../../../formatters/source/pushResultFormatter'; import { ProgressFormatter } from '../../../formatters/progressFormatter'; @@ -22,41 +30,51 @@ Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'push'); const deployMessages = Messages.loadMessages('@salesforce/plugin-source', 'deployCommand'); +const replacement = 'project deploy start'; + export default class Push extends DeployCommand { - public static aliases = ['force:source:beta:push']; + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; public static description = messages.getMessage('description'); - public static help = messages.getMessage('help'); - protected static readonly flagsConfig: FlagsConfig = { - forceoverwrite: flags.boolean({ + public static summary = messages.getMessage('summary'); + public static examples = messages.getMessages('examples'); + public static requiresProject = true; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + forceoverwrite: Flags.boolean({ char: 'f', - description: messages.getMessage('flags.forceoverwrite'), - longDescription: messages.getMessage('flags.forceoverwriteLong'), + summary: messages.getMessage('flags.forceoverwrite.summary'), }), - wait: flags.minutes({ + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(DeployCommand.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.waitLong'), - longDescription: messages.getMessage('flags.waitLong'), + min: 1, + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), }), - ignorewarnings: flags.boolean({ + ignorewarnings: Flags.boolean({ char: 'g', - description: messages.getMessage('flags.ignorewarnings'), - longDescription: messages.getMessage('flags.ignorewarningsLong'), + summary: messages.getMessage('flags.ignorewarnings.summary'), }), - quiet: flags.builtin({ - description: messages.getMessage('flags.quiet'), + quiet: Flags.boolean({ + summary: messages.getMessage('flags.quiet.summary'), }), }; - protected static requiresUsername = true; - protected static requiresProject = true; protected readonly lifecycleEventNames = ['predeploy', 'postdeploy']; private deployResults: DeployResult[] = []; private tracking: SourceTracking; private deletes: string[]; + private flags: Interfaces.InferredFlags; public async run(): Promise { + this.flags = (await this.parse(Push)).flags; await this.prechecks(); await this.deploy(); this.resolveSuccess(); @@ -67,10 +85,10 @@ export default class Push extends DeployCommand { protected async prechecks(): Promise { this.tracking = await trackingSetup({ commandName: 'force:source:push', - ignoreConflicts: this.getFlag('forceoverwrite', false), - org: this.org, + ignoreConflicts: this.flags.forceoverwrite ?? false, + org: this.flags['target-org'], project: this.project, - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), }); // we need these later to show deletes in results @@ -78,6 +96,7 @@ export default class Push extends DeployCommand { } protected async deploy(): Promise { + const username = this.flags['target-org'].getUsername(); const isSequentialDeploy = getBoolean( await this.project.resolveProjectConfig(), 'pushPackageDirectoriesSequentially', @@ -90,12 +109,12 @@ export default class Push extends DeployCommand { ]); // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionDeploy', async (apiData: DeployVersionData) => { - this.ux.log( + Lifecycle.getInstance().on('apiVersionDeploy', async (apiData: DeployVersionData) => { + this.log( deployMessages.getMessage('apiVersionMsgDetailed', [ 'Pushing', apiData.manifestVersion, - this.org.getUsername(), + username, apiData.apiVersion, apiData.webService, ]) @@ -113,43 +132,41 @@ export default class Push extends DeployCommand { // there might have been components in local tracking, but they might be ignored by SDR or unresolvable. // SDR will throw when you try to resolve them, so don't if (componentSet.size === 0) { - this.logger.warn('There are no changes to deploy'); + this.warn('There are no changes to deploy'); continue; } // fire predeploy event for sync and async deploys - await this.lifecycle.emit('predeploy', componentSet.toArray()); - - const username = this.org.getUsername(); + await Lifecycle.getInstance().emit('predeploy', componentSet.toArray()); const deploy = await componentSet.deploy({ usernameOrConnection: username, apiOptions: { - ignoreWarnings: this.getFlag('ignorewarnings', false), + ignoreWarnings: this.flags.ignorewarnings ?? false, rest: isRest, testLevel: 'NoTestRun', }, }); // we're not print JSON output - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { const progressFormatter: ProgressFormatter = env.getBoolean('SFDX_USE_PROGRESS_BAR', true) - ? new DeployProgressBarFormatter(this.logger, this.ux) - : new DeployProgressStatusFormatter(this.logger, this.ux); + ? new DeployProgressBarFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })) + : new DeployProgressStatusFormatter(new Ux({ jsonEnabled: this.jsonEnabled() })); progressFormatter.progress(deploy); } - const result = await deploy.pollStatus({ timeout: this.getFlag('wait') }); + const result = await deploy.pollStatus({ timeout: this.flags.wait }); if (result) { // Only fire the postdeploy event when we have results. I.e., not async. - await this.lifecycle.emit('postdeploy', result); + await Lifecycle.getInstance().emit('postdeploy', result); this.deployResults.push(result); if ( result.response.status !== RequestStatus.Succeeded && isSequentialDeploy && this.project.hasMultiplePackages() ) { - this.ux.log(messages.getMessage('sequentialFail')); + this.log(messages.getMessage('sequentialFail')); break; } } @@ -163,7 +180,7 @@ export default class Push extends DeployCommand { return; } await updateTracking({ - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), result: this.deployResults[0], // it doesn't matter which one--it's just used to determine if it's deploy or retrieve tracking: this.tracking, // since we're going to poll source members, we want them all in one transaction @@ -214,25 +231,45 @@ export default class Push extends DeployCommand { return this.setExitCode(1); } - this.logger.warn( - 'Unexpected exit code', - this.deployResults.map((result) => result.response) - ); + this.warn(` Unexpected exit code ${this.deployResults.map((result) => result.response.errorMessage).join(', ')}`); this.setExitCode(1); } + protected catch(error: Error | SfError | SfCommand.Error): Promise { + const formatter = new PushResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + { + quiet: this.flags.quiet ?? false, + }, + this.deployResults, + this.deletes + ); + try { + formatter.getJson(); + } catch (e) { + this.logJson(this.toErrorJson(e as SfCommand.Error)); + } + + throw error; + } + protected formatResult(): PushResponse { if (!this.deployResults.length) { - this.ux.log('No results found'); + this.log('No results found'); } const formatterOptions = { - quiet: this.getFlag('quiet', false), + quiet: this.flags.quiet ?? false, }; - const formatter = new PushResultFormatter(this.logger, this.ux, formatterOptions, this.deployResults, this.deletes); + const formatter = new PushResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.deployResults, + this.deletes + ); // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } diff --git a/src/commands/force/source/retrieve.ts b/src/commands/force/source/retrieve.ts index 540c2b73d..151d5c06f 100644 --- a/src/commands/force/source/retrieve.ts +++ b/src/commands/force/source/retrieve.ts @@ -5,11 +5,10 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import * as os from 'os'; import { dirname, join, resolve } from 'path'; import * as fs from 'fs'; -import { flags, FlagsConfig } from '@salesforce/command'; -import { Messages, SfError, SfProject } from '@salesforce/core'; + +import { Lifecycle, Messages, SfError, SfProject } from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { ComponentSet, @@ -20,6 +19,15 @@ import { RegistryAccess, } from '@salesforce/source-deploy-retrieve'; import { SourceTracking } from '@salesforce/source-tracking'; +import { Interfaces } from '@oclif/core'; +import { + arrayWithDeprecation, + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + Ux, +} from '@salesforce/sf-plugins-core'; import { SourceCommand } from '../../../sourceCommand'; import { PackageRetrieval, @@ -32,74 +40,88 @@ import { promisesQueue } from '../../../promiseQueue'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); const spinnerMessages = Messages.loadMessages('@salesforce/plugin-source', 'spinner'); -const retrieveMessages = Messages.load('@salesforce/plugin-source', 'retrieve', ['apiVersionMsgDetailed']); +const retrieveMessages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); + +const replacement = 'project retrieve start'; export class Retrieve extends SourceCommand { + public static readonly summary = messages.getMessage('summary'); public static readonly description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); + public static readonly examples = messages.getMessages('examples'); public static readonly requiresProject = true; public static readonly requiresUsername = true; - public static readonly flagsConfig: FlagsConfig = { - retrievetargetdir: flags.directory({ + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + retrievetargetdir: Flags.directory({ char: 'r', - description: messages.getMessage('flags.retrievetargetdir'), - longDescription: messages.getMessage('flagsLong.retrievetargetdir'), + description: messages.getMessage('flags.retrievetargetdir.description'), + summary: messages.getMessage('flags.retrievetargetdir.summary'), exclusive: ['packagenames', 'sourcepath'], }), - apiversion: flags.builtin({ + apiversion: Flags.string({ /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */ // @ts-ignore force char override for backward compat char: 'a', }), - sourcepath: flags.array({ + sourcepath: arrayWithDeprecation({ char: 'p', - description: messages.getMessage('flags.sourcePath'), - longDescription: messages.getMessage('flagsLong.sourcePath'), + description: messages.getMessage('flags.sourcePath.description'), + summary: messages.getMessage('flags.sourcePath.summary'), exclusive: ['manifest', 'metadata'], }), - wait: flags.minutes({ + wait: Flags.duration({ + unit: 'minutes', char: 'w', default: Duration.minutes(SourceCommand.DEFAULT_WAIT_MINUTES), - min: Duration.minutes(1), - description: messages.getMessage('flags.wait'), - longDescription: messages.getMessage('flagsLong.wait'), + min: 1, + description: messages.getMessage('flags.wait.description'), + summary: messages.getMessage('flags.wait.summary'), }), - manifest: flags.filepath({ + manifest: Flags.file({ char: 'x', - description: messages.getMessage('flags.manifest'), - longDescription: messages.getMessage('flagsLong.manifest'), + description: messages.getMessage('flags.manifest.description'), + summary: messages.getMessage('flags.manifest.summary'), exclusive: ['metadata', 'sourcepath'], }), - metadata: flags.array({ + metadata: arrayWithDeprecation({ char: 'm', - description: messages.getMessage('flags.metadata'), - longDescription: messages.getMessage('flagsLong.metadata'), + description: messages.getMessage('flags.metadata.description'), + summary: messages.getMessage('flags.metadata.summary'), exclusive: ['manifest', 'sourcepath'], }), - packagenames: flags.array({ + packagenames: arrayWithDeprecation({ char: 'n', - description: messages.getMessage('flags.packagename'), + summary: messages.getMessage('flags.packagename.summary'), }), - tracksource: flags.boolean({ + tracksource: Flags.boolean({ char: 't', - description: messages.getMessage('flags.tracksource'), + summary: messages.getMessage('flags.tracksource.summary'), }), - forceoverwrite: flags.boolean({ + forceoverwrite: Flags.boolean({ char: 'f', - description: messages.getMessage('flags.forceoverwrite'), + summary: messages.getMessage('flags.forceoverwrite.summary'), dependsOn: ['tracksource'], }), - verbose: flags.builtin({ - description: messages.getMessage('flags.verbose'), + verbose: Flags.boolean({ + summary: messages.getMessage('flags.verbose.summary'), }), }; protected readonly lifecycleEventNames = ['preretrieve', 'postretrieve']; protected retrieveResult: RetrieveResult; protected tracking: SourceTracking; private resolvedTargetDir: string; + private flags: Interfaces.InferredFlags; private registry = new RegistryAccess(); public async run(): Promise { + this.flags = (await this.parse(Retrieve)).flags; await this.preChecks(); await this.retrieve(); this.resolveSuccess(); @@ -110,9 +132,9 @@ export class Retrieve extends SourceCommand { protected async preChecks(): Promise { if (this.flags.retrievetargetdir) { - this.resolvedTargetDir = resolve(this.flags.retrievetargetdir as string); + this.resolvedTargetDir = resolve(this.flags.retrievetargetdir); if (this.overlapsPackage()) { - throw messages.createError('retrieveTargetDirOverlapsPackage', [this.flags.retrievetargetdir as string]); + throw messages.createError('retrieveTargetDirOverlapsPackage', [this.flags.retrievetargetdir]); } } // we need something to retrieve @@ -122,8 +144,8 @@ export class Retrieve extends SourceCommand { } if (this.flags.tracksource) { this.tracking = await trackingSetup({ - ux: this.ux, - org: this.org, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + org: this.flags['target-org'], project: this.project, ignoreConflicts: true, commandName: 'force:source:retrieve', @@ -132,10 +154,10 @@ export class Retrieve extends SourceCommand { } protected async retrieve(): Promise { - const username = this.org.getUsername(); + const username = this.flags['target-org'].getUsername(); // eslint-disable-next-line @typescript-eslint/require-await - this.lifecycle.on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { - this.ux.log( + Lifecycle.getInstance().on('apiVersionRetrieve', async (apiData: RetrieveVersionData) => { + this.log( retrieveMessages.getMessage('apiVersionMsgDetailed', [ 'Retrieving', apiData.manifestVersion, @@ -144,35 +166,39 @@ export class Retrieve extends SourceCommand { ]) ); }); - this.ux.startSpinner(spinnerMessages.getMessage('retrieve.componentSetBuild')); + this.spinner.start(spinnerMessages.getMessage('retrieve.componentSetBuild')); this.componentSet = await ComponentSetBuilder.build({ - apiversion: this.getFlag('apiversion'), + apiversion: this.flags.apiversion, sourceapiversion: await this.getSourceApiVersion(), - packagenames: this.getFlag('packagenames'), - sourcepath: this.getFlag('sourcepath'), + packagenames: this.flags.packagenames, + sourcepath: this.flags.sourcepath, manifest: this.flags.manifest && { - manifestPath: this.getFlag('manifest'), + manifestPath: this.flags.manifest, directoryPaths: this.flags.retrievetargetdir ? [] : this.getPackageDirs(), }, metadata: this.flags.metadata && { - metadataEntries: this.getFlag('metadata'), + metadataEntries: this.flags.metadata, directoryPaths: this.flags.retrievetargetdir ? [] : this.getPackageDirs(), }, }); - if (this.getFlag('manifest') || this.getFlag('metadata')) { + if (this.flags.manifest || this.flags.metadata) { if (this.wantsToRetrieveCustomFields()) { - this.ux.warn(messages.getMessage('wantsToRetrieveCustomFields')); + this.warn(messages.getMessage('wantsToRetrieveCustomFields')); this.componentSet.add({ fullName: ComponentSet.WILDCARD, type: this.registry.getTypeByName('CustomObject'), }); } } - if (this.getFlag('tracksource')) { + if (this.flags.tracksource) { // will throw if conflicts exist - if (!this.getFlag('forceoverwrite')) { - await filterConflictsByComponentSet({ tracking: this.tracking, components: this.componentSet, ux: this.ux }); + if (!this.flags.forceoverwrite) { + await filterConflictsByComponentSet({ + tracking: this.tracking, + components: this.componentSet, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + }); } const remoteDeletes = await this.tracking.getChanges({ @@ -181,25 +207,25 @@ export class Retrieve extends SourceCommand { format: 'string', }); if (remoteDeletes.length) { - this.ux.warn(messages.getMessage('retrieveWontDelete')); + this.warn(messages.getMessage('retrieveWontDelete')); } } - await this.lifecycle.emit('preretrieve', this.componentSet.toArray()); + await Lifecycle.getInstance().emit('preretrieve', this.componentSet.toArray()); - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.sendingRequest')); + this.spinner.status = spinnerMessages.getMessage('retrieve.sendingRequest'); const mdapiRetrieve = await this.componentSet.retrieve({ usernameOrConnection: username, merge: true, output: this.resolvedTargetDir || this.project.getDefaultPackage().fullPath, - packageOptions: this.getFlag('packagenames'), + packageOptions: this.flags.packagenames, }); - this.ux.setSpinnerStatus(spinnerMessages.getMessage('retrieve.polling')); - this.retrieveResult = await mdapiRetrieve.pollStatus({ timeout: this.getFlag('wait') }); + this.spinner.status = spinnerMessages.getMessage('retrieve.polling'); + this.retrieveResult = await mdapiRetrieve.pollStatus({ timeout: this.flags.wait }); - await this.lifecycle.emit('postretrieve', this.retrieveResult.getFileResponses()); - this.ux.stopSpinner(); + await Lifecycle.getInstance().emit('postretrieve', this.retrieveResult.getFileResponses()); + this.spinner.stop(); } protected resolveSuccess(): void { @@ -219,19 +245,23 @@ export class Retrieve extends SourceCommand { const packages: PackageRetrieval[] = []; const projectPath = await SfProject.resolveProjectPath(); - this.getFlag('packagenames', []).forEach((name) => { + (this.flags.packagenames ?? []).forEach((name) => { packages.push({ name, path: join(projectPath, name) }); }); const formatterOptions = { - waitTime: this.getFlag('wait').quantity, - verbose: this.getFlag('verbose', false), + waitTime: this.flags.wait.quantity, + verbose: this.flags.verbose ?? false, packages, }; - const formatter = new RetrieveResultFormatter(this.logger, this.ux, formatterOptions, this.retrieveResult); + const formatter = new RetrieveResultFormatter( + new Ux({ jsonEnabled: this.jsonEnabled() }), + formatterOptions, + this.retrieveResult + ); // Only display results to console when JSON flag is unset. - if (!this.isJsonOutput()) { + if (!this.jsonEnabled()) { formatter.display(); } @@ -239,8 +269,12 @@ export class Retrieve extends SourceCommand { } private async maybeUpdateTracking(): Promise { - if (this.getFlag('tracksource', false)) { - return updateTracking({ tracking: this.tracking, result: this.retrieveResult, ux: this.ux }); + if (this.flags.tracksource ?? false) { + return updateTracking({ + tracking: this.tracking, + result: this.retrieveResult, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), + }); } } @@ -301,7 +335,7 @@ export class Retrieve extends SourceCommand { // move contents of 'main/default' to 'retrievetargetdir' await promisesQueue([join(this.resolvedTargetDir, 'main', 'default')], mv, 5, true); // remove 'main/default' - await fs.promises.rm(join(this.flags.retrievetargetdir as string, 'main'), { recursive: true }); + await fs.promises.rm(join(this.flags.retrievetargetdir, 'main'), { recursive: true }); this.retrieveResult.getFileResponses().forEach((fileResponse) => { fileResponse.filePath = fileResponse.filePath?.replace(join('main', 'default'), ''); }); diff --git a/src/commands/force/source/status.ts b/src/commands/force/source/status.ts index dafb85cf0..1568f9616 100644 --- a/src/commands/force/source/status.ts +++ b/src/commands/force/source/status.ts @@ -5,55 +5,71 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import * as os from 'os'; -import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command'; import { Messages } from '@salesforce/core'; import { ChangeResult, StatusOutputRow } from '@salesforce/source-tracking'; +import { Interfaces } from '@oclif/core'; +import { + Flags, + loglevel, + orgApiVersionFlagWithDeprecations, + requiredOrgFlagWithDeprecations, + SfCommand, + Ux, +} from '@salesforce/sf-plugins-core'; import { StatusFormatter, StatusResult } from '../../../formatters/source/statusFormatter'; import { trackingSetup } from '../../../trackingFunctions'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'status'); -export default class Status extends SfdxCommand { - public static aliases = ['force:source:beta:status']; - public static description = messages.getMessage('description'); - public static readonly examples = messages.getMessage('examples').split(os.EOL); - protected static flagsConfig: FlagsConfig = { - local: flags.boolean({ +export type StatusCommandResult = StatusResult[]; + +const replacement = 'project retrieve/deploy preview'; +export default class Status extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'deprecated'; + public static readonly deprecationOptions = { + to: replacement, + message: messages.getMessage('deprecation', [replacement]), + }; + public static readonly flags = { + 'api-version': orgApiVersionFlagWithDeprecations, + loglevel, + 'target-org': requiredOrgFlagWithDeprecations, + local: Flags.boolean({ char: 'l', - description: messages.getMessage('flags.local'), - longDescription: messages.getMessage('flags.localLong'), + summary: messages.getMessage('flags.local.summary'), exclusive: ['remote'], }), - remote: flags.boolean({ + remote: Flags.boolean({ char: 'r', - description: messages.getMessage('flags.remote'), - longDescription: messages.getMessage('flags.remoteLong'), + summary: messages.getMessage('flags.remote.summary'), exclusive: ['local'], }), - concise: flags.builtin({ - description: messages.getMessage('flags.concise'), + concise: Flags.boolean({ + summary: messages.getMessage('flags.concise.summary'), }), }; - protected static requiresUsername = true; - protected static requiresProject = true; + public static readonly requiresProject = true; protected results = new Array(); protected localAdds: ChangeResult[] = []; + private flags: Interfaces.InferredFlags; - public async run(): Promise { + public async run(): Promise { + this.flags = (await this.parse(Status)).flags; const tracking = await trackingSetup({ commandName: 'force:source:status', ignoreConflicts: true, - org: this.org, + org: this.flags['target-org'], project: this.project, - ux: this.ux, + ux: new Ux({ jsonEnabled: this.jsonEnabled() }), }); - const wantsLocal = (this.flags.local as boolean) || (!this.flags.remote && !this.flags.local); - const wantsRemote = (this.flags.remote as boolean) || (!this.flags.remote && !this.flags.local); + const wantsLocal = this.flags.local || (!this.flags.remote && !this.flags.local); + const wantsRemote = this.flags.remote || (!this.flags.remote && !this.flags.local); - this.logger.debug( + this.debug( `project is ${this.project.getPath()} and pkgDirs are ${this.project .getPackageDirectories() .map((dir) => dir.path) @@ -68,9 +84,8 @@ export default class Status extends SfdxCommand { protected formatResult(): StatusResult[] { const formatter = new StatusFormatter( - this.logger, - this.ux, - { concise: this.flags.concise as boolean }, + new Ux({ jsonEnabled: this.jsonEnabled() }), + { concise: this.flags.concise }, this.results ); diff --git a/src/commands/force/source/tracking/clear.ts b/src/commands/force/source/tracking/clear.ts deleted file mode 100644 index a456c437d..000000000 --- a/src/commands/force/source/tracking/clear.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import * as chalk from 'chalk'; -import { SourceTracking, throwIfInvalid } from '@salesforce/source-tracking'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'tracking'); - -export type SourceTrackingClearResult = { - clearedFiles: string[]; -}; - -export class Clear extends SfdxCommand { - public static aliases = ['force:source:beta:tracking:clear']; - public static readonly description = messages.getMessage('clearDescription'); - public static readonly requiresProject = true; - public static readonly requiresUsername = true; - - public static readonly flagsConfig: FlagsConfig = { - noprompt: flags.boolean({ - char: 'p', - description: messages.getMessage('nopromptDescription'), - required: false, - }), - }; - - public async run(): Promise { - throwIfInvalid({ - org: this.org, - projectPath: this.project.getPath(), - toValidate: 'plugin-source', - command: 'force:source:tracking:clear', - }); - let clearedFiles: string[] = []; - if (this.flags.noprompt || (await this.ux.confirm(chalk.dim(messages.getMessage('promptMessage'))))) { - const sourceTracking = await SourceTracking.create({ - project: this.project, - org: this.org, - }); - clearedFiles = await Promise.all([sourceTracking.clearLocalTracking(), sourceTracking.clearRemoteTracking()]); - this.ux.log('Cleared local tracking files.'); - } - return { clearedFiles }; - } -} diff --git a/src/commands/force/source/tracking/reset.ts b/src/commands/force/source/tracking/reset.ts deleted file mode 100644 index a343fcbd1..000000000 --- a/src/commands/force/source/tracking/reset.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command'; -import { Messages } from '@salesforce/core'; -import * as chalk from 'chalk'; -import { SourceTracking, throwIfInvalid } from '@salesforce/source-tracking'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'tracking'); - -export type SourceTrackingResetResult = { - sourceMembersSynced: number; - localPathsSynced: number; -}; - -export class Reset extends SfdxCommand { - public static aliases = ['force:source:beta:tracking:reset']; - public static readonly description = messages.getMessage('resetDescription'); - public static readonly requiresProject = true; - public static readonly requiresUsername = true; - - public static readonly flagsConfig: FlagsConfig = { - revision: flags.integer({ - char: 'r', - description: messages.getMessage('revisionDescription'), - min: 0, - }), - noprompt: flags.boolean({ - char: 'p', - description: messages.getMessage('nopromptDescription'), - }), - }; - - public async run(): Promise { - throwIfInvalid({ - org: this.org, - projectPath: this.project.getPath(), - toValidate: 'plugin-source', - command: 'force:source:tracking:clear', - }); - - if (this.flags.noprompt || (await this.ux.confirm(chalk.dim(messages.getMessage('promptMessage'))))) { - const sourceTracking = await SourceTracking.create({ - project: this.project, - org: this.org, - }); - - const [remoteResets, localResets] = await Promise.all([ - sourceTracking.resetRemoteTracking(this.flags.revision as number), - sourceTracking.resetLocalTracking(), - ]); - - this.ux.log( - `Reset local tracking files${this.flags.revision ? ` to revision ${this.flags.revision as number}` : ''}.` - ); - - return { - sourceMembersSynced: remoteResets, - localPathsSynced: localResets.length, - }; - } - - return { - sourceMembersSynced: 0, - localPathsSynced: 0, - }; - } -} diff --git a/src/coverageUtils.ts b/src/coverageUtils.ts index fdd57f87d..7bcf7f829 100644 --- a/src/coverageUtils.ts +++ b/src/coverageUtils.ts @@ -99,7 +99,7 @@ export function transformDeployTestsResultsToTestResult( ): TestResult { const numTestsRun = parseInt(runTestResult.numTestsRun, 10); const numTestFailures = parseInt(runTestResult.numFailures, 10); - const testResult: TestResult = { + return { summary: { commandTimeInMs: 0, failRate: ((numTestFailures / numTestsRun) * 100).toFixed(2) + '%', @@ -142,5 +142,4 @@ export function transformDeployTestsResultsToTestResult( return codeCoverageResult; }), }; - return testResult; } diff --git a/src/deployCommand.ts b/src/deployCommand.ts index a6d0253f0..b61eb37ac 100644 --- a/src/deployCommand.ts +++ b/src/deployCommand.ts @@ -15,7 +15,7 @@ import { MetadataApiDeployStatus, RequestStatus, } from '@salesforce/source-deploy-retrieve'; -import { Messages, PollingClient, SfdxPropertyKeys, SfError, StatusResult } from '@salesforce/core'; +import { Connection, Messages, Org, PollingClient, SfdxPropertyKeys, SfError, StatusResult } from '@salesforce/core'; import { AnyJson, getBoolean, isString } from '@salesforce/ts-types'; import { Duration, once, ensureArray } from '@salesforce/kit'; import { @@ -32,17 +32,13 @@ import { transformCoverageToApexCoverage, transformDeployTestsResultsToTestResul export type TestLevel = 'NoTestRun' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'deployCommand', [ - 'invalidDeployId', - 'MissingDeployId', - 'resultsDirMissing', -]); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'deployCommand'); export const reportsFormatters = Object.keys(DefaultReportOptions); export abstract class DeployCommand extends SourceCommand { protected displayDeployId = once((id: string) => { - if (!this.isJsonOutput()) { - this.ux.log(`Deploy ID: ${id}`); + if (!this.jsonEnabled()) { + this.log(`Deploy ID: ${id}`); } }); @@ -57,26 +53,17 @@ export abstract class DeployCommand extends SourceCommand { const stashKey = Stash.getKey(this.id); Stash.set(stashKey, { jobid: id }); }); - - // the basic sfdx flag is already making sure its of the correct length - public static isValidDeployId = (id: string): boolean => { - if (id.startsWith('0Af')) { - return true; - } else { - throw new SfError(messages.getMessage('invalidDeployId'), 'invalidDeployId'); - } - }; /** * Request a report of an in-progress or completed deployment. * * @param id the Deploy ID of a deployment request * @returns DeployResult */ - protected async report(id?: string): Promise { + protected async report(conn: Connection, id?: string): Promise { const deployId = this.resolveDeployId(id); this.displayDeployId(deployId); - const res = await this.org.getConnection().metadata.checkDeployStatus(deployId, true); + const res = await conn.metadata.checkDeployStatus(deployId, true); const deployStatus = res as unknown as MetadataApiDeployStatus; const componentSet = this.componentSet || new ComponentSet(); @@ -108,8 +95,9 @@ export abstract class DeployCommand extends SourceCommand { * * @param id */ - protected createDeploy(id?: string): MetadataApiDeploy { - return new MetadataApiDeploy({ usernameOrConnection: this.org.getUsername(), id }); + // eslint-disable-next-line class-methods-use-this + protected createDeploy(conn: Connection, id?: string): MetadataApiDeploy { + return new MetadataApiDeploy({ usernameOrConnection: conn.getUsername(), id }); } protected resolveDeployId(id?: string): string { @@ -127,36 +115,39 @@ export abstract class DeployCommand extends SourceCommand { // SOAP is the default unless: // 1. SOAP is specified with the soapdeploy flag on the command // 2. The restDeploy SFDX config setting is explicitly true. - protected isRestDeploy(): boolean { - if (getBoolean(this.flags, 'soapdeploy') === true) { - this.logger.debug('soapdeploy flag === true. Using SOAP'); + protected isRestDeploy(soapdeploy = true): boolean { + if (soapdeploy === true) { + this.debug('soapdeploy flag === true. Using SOAP'); return false; } const restDeployConfig = this.configAggregator.getInfo(SfdxPropertyKeys.REST_DEPLOY).value; // aggregator property values are returned as strings if (restDeployConfig === 'false') { - this.logger.debug('restDeploy SFDX config === false. Using SOAP'); + this.debug('restDeploy SFDX config === false. Using SOAP'); return false; } else if (restDeployConfig === 'true') { - this.logger.debug('restDeploy SFDX config === true. Using REST'); + this.debug('restDeploy SFDX config === true. Using REST'); return true; } else { - this.logger.debug('soapdeploy flag unset. restDeploy SFDX config unset. Defaulting to SOAP'); + this.debug('soapdeploy flag unset. restDeploy SFDX config unset. Defaulting to SOAP'); } return false; } - protected async poll(deployId: string, options?: Partial): Promise { - const waitFlag = this.getFlag('wait'); - const waitDuration = waitFlag.minutes === -1 ? Duration.days(7) : waitFlag; + protected async poll( + connection: Connection, + deployId: string, + options: Partial & { wait: Duration } = { wait: Duration.days(7) } + ): Promise { + const waitDuration = options.wait; const defaultOptions: PollingClient.Options = { frequency: options?.frequency ?? Duration.seconds(1), timeout: options?.timeout ?? waitDuration, poll: async (): Promise => { - const deployResult = await this.report(deployId); + const deployResult = await this.report(connection, deployId); return { completed: getBoolean(deployResult, 'response.done'), payload: deployResult as unknown as AnyJson, @@ -168,9 +159,8 @@ export abstract class DeployCommand extends SourceCommand { return pollingClient.subscribe() as unknown as Promise; } - protected async deployRecentValidation(): Promise { - const id = this.getFlag('validateddeployrequestid'); - const response = await this.org.getConnection().deployRecentValidation({ id, rest: this.isRest }); + protected async deployRecentValidation(id: string, conn: Connection): Promise { + const response = await conn.deployRecentValidation({ id, rest: this.isRest }); // This is the deploy ID of the deployRecentValidation response, not // the already validated deploy ID (i.e., validateddeployrequestid). // REST returns an object with an ID, SOAP returns the id as a string. @@ -178,24 +168,24 @@ export abstract class DeployCommand extends SourceCommand { this.updateDeployId(validatedDeployId); this.asyncDeployResult = { id: validatedDeployId }; - return this.isAsync ? this.report(validatedDeployId) : this.poll(validatedDeployId); + return this.isAsync ? this.report(conn, validatedDeployId) : this.poll(conn, validatedDeployId); } - protected maybeCreateRequestedReports(): void { + protected maybeCreateRequestedReports(options: { coverageformatters: string[]; junit: boolean; org: Org }): void { // only generate reports if test results are present if (this.deployResult.response?.numberTestsTotal) { - if (this.flags.coverageformatters) { - createCoverageReport(this.deployResult, this.flags.coverageformatters as string[], 'no-map', this.resultsDir); + if (options.coverageformatters) { + createCoverageReport(this.deployResult, options.coverageformatters, 'no-map', this.resultsDir); } - if (this.flags.junit) { - this.createJunitResults(this.deployResult); + if (options.junit) { + this.createJunitResults(this.deployResult, options.org); } } } - protected createJunitResults(deployResult: DeployResult): void { + protected createJunitResults(deployResult: DeployResult, org: Org): void { const testResult = transformDeployTestsResultsToTestResult( - this.org.getConnection(), + org.getConnection(), deployResult.response?.details?.runTestResult ); if (testResult.summary.testsRan > 0) { diff --git a/src/formatters/convertResultFormatter.ts b/src/formatters/convertResultFormatter.ts deleted file mode 100644 index 5b21cf197..000000000 --- a/src/formatters/convertResultFormatter.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import { resolve } from 'path'; -import { UX } from '@salesforce/command'; -import { Logger, Messages, SfError } from '@salesforce/core'; -import { ConvertResult } from '@salesforce/source-deploy-retrieve'; -import { ResultFormatter } from './resultFormatter'; - -Messages.importMessagesDirectory(__dirname); -const messages = Messages.loadMessages('@salesforce/plugin-source', 'convert'); - -export interface ConvertCommandResult { - location: string; -} - -export class ConvertResultFormatter extends ResultFormatter { - protected result: ConvertResult; - - public constructor(logger: Logger, ux: UX, result: ConvertResult) { - super(logger, ux); - this.result = result; - } - - public getJson(): ConvertCommandResult { - return { - location: resolve(this.result.packagePath), - }; - } - - public display(): void { - if (this.isSuccess()) { - this.ux.log(messages.getMessage('success', [this.result.packagePath])); - } else { - throw new SfError(messages.getMessage('convertFailed'), 'ConvertFailed'); - } - } -} diff --git a/src/formatters/deployCancelResultFormatter.ts b/src/formatters/deployCancelResultFormatter.ts index 5f77ca7da..f639d9d80 100644 --- a/src/formatters/deployCancelResultFormatter.ts +++ b/src/formatters/deployCancelResultFormatter.ts @@ -5,10 +5,9 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { getString } from '@salesforce/ts-types'; import { DeployResult, MetadataApiDeployStatus } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter } from './resultFormatter'; export type DeployCancelCommandResult = MetadataApiDeployStatus; @@ -16,8 +15,8 @@ export type DeployCancelCommandResult = MetadataApiDeployStatus; export class DeployCancelResultFormatter extends ResultFormatter { protected result: DeployResult; - public constructor(logger: Logger, ux: UX, result: DeployResult) { - super(logger, ux); + public constructor(ux: Ux, result: DeployResult) { + super(ux); this.result = result; } @@ -35,7 +34,7 @@ export class DeployCancelResultFormatter extends ResultFormatter { if (errMsgDueTo) { errMsg = `${errMsg} Due to: ${errMsgDueTo}`; } - this.ux.error(errMsg); + this.ux.warn(errMsg); } } } diff --git a/src/formatters/deployProgressBarFormatter.ts b/src/formatters/deployProgressBarFormatter.ts index 09c002612..6d76e07d5 100644 --- a/src/formatters/deployProgressBarFormatter.ts +++ b/src/formatters/deployProgressBarFormatter.ts @@ -4,18 +4,18 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; + import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; import { once } from '@salesforce/kit'; import { ux as coreUx } from '@oclif/core'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ProgressBar } from '../types'; import { ProgressFormatter } from './progressFormatter'; export class DeployProgressBarFormatter extends ProgressFormatter { protected progressBar?: ProgressBar; - public constructor(logger: Logger, ux: UX) { - super(logger, ux); + public constructor(ux: Ux) { + super(ux); } // displays the progress of the Deployment @@ -68,7 +68,7 @@ export class DeployProgressBarFormatter extends ProgressFormatter { // used to initialize the progress bar protected initProgressBar(): void { - this.logger.debug('initializing progress bar'); + // this.logger.debug('initializing progress bar'); this.progressBar = coreUx.progress({ format: 'DEPLOY PROGRESS | {bar} | {value}/{total} Components', barCompleteChar: '\u2588', diff --git a/src/formatters/deployProgressStatusFormatter.ts b/src/formatters/deployProgressStatusFormatter.ts index db6e2fb53..dae5e531b 100644 --- a/src/formatters/deployProgressStatusFormatter.ts +++ b/src/formatters/deployProgressStatusFormatter.ts @@ -5,18 +5,17 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import * as chalk from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { getNumber } from '@salesforce/ts-types'; import { MetadataApiDeploy, MetadataApiDeployStatus } from '@salesforce/source-deploy-retrieve'; import { Duration } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ProgressFormatter } from './progressFormatter'; import { ResultFormatterOptions } from './resultFormatter'; export class DeployProgressStatusFormatter extends ProgressFormatter { private previousComponents = -1; private previousTests = -1; - public constructor(logger: Logger, ux: UX, private options?: Pick) { - super(logger, ux); + public constructor(ux: Ux, private options?: ResultFormatterOptions) { + super(ux); } // This can be used to print the progress of the deployment. diff --git a/src/formatters/deployReportResultFormatter.ts b/src/formatters/deployReportResultFormatter.ts index 91d055527..7c4e9c331 100644 --- a/src/formatters/deployReportResultFormatter.ts +++ b/src/formatters/deployReportResultFormatter.ts @@ -47,7 +47,7 @@ export class DeployReportResultFormatter extends DeployResultFormatter { } if (status === RequestStatus.Failed) { - const messages = Messages.load('@salesforce/plugin-source', 'report', ['mdapiDeployFailed']); + const messages = Messages.loadMessages('@salesforce/plugin-source', 'report'); throw new SfError(messages.getMessage('mdapiDeployFailed'), 'mdapiDeployFailed'); } diff --git a/src/formatters/deployResultFormatter.ts b/src/formatters/deployResultFormatter.ts index 73b0f5d60..8200f9846 100644 --- a/src/formatters/deployResultFormatter.ts +++ b/src/formatters/deployResultFormatter.ts @@ -7,17 +7,21 @@ import * as path from 'path'; import * as chalk from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger, Messages, SfError } from '@salesforce/core'; + +import { Messages, SfError } from '@salesforce/core'; import { ensureArray } from '@salesforce/kit'; import { asString, get, getBoolean, getNumber, getString } from '@salesforce/ts-types'; import { DeployMessage, DeployResult, + Failures, FileResponse, + FileResponseFailure, MetadataApiDeployStatus, RequestStatus, + Successes, } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { prepCoverageForDisplay } from '../coverageUtils'; import { ResultFormatter, ResultFormatterOptions } from './resultFormatter'; import { MdDeployResult } from './mdapi/mdDeployResultFormatter'; @@ -25,21 +29,21 @@ import { MdDeployResult } from './mdapi/mdDeployResultFormatter'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'deploy'); -export interface DeployCommandResult extends MdDeployResult { +export type DeployCommandResult = { deletedSource?: FileResponse[]; deployedSource: FileResponse[]; outboundFiles: string[]; deploys: MetadataApiDeployStatus[]; deletes?: MetadataApiDeployStatus[]; replacements?: Record; -} +} & MdDeployResult; export class DeployResultFormatter extends ResultFormatter { protected result: DeployResult; protected fileResponses: FileResponse[]; - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, result: DeployResult) { - super(logger, ux, options); + public constructor(ux: Ux, options: ResultFormatterOptions, result: DeployResult) { + super(ux, options); this.result = result; this.fileResponses = result?.getFileResponses ? result.getFileResponses() : []; } @@ -149,11 +153,19 @@ export class DeployResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.blue('Deployed Source')); - this.ux.table(successes, { - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); + this.ux.table( + successes.map((success) => ({ + state: success.state, + fullName: success.fullName, + type: success.type, + filePath: success.filePath, + })), + { + fullName: { header: 'FULL NAME' }, + type: { header: 'TYPE' }, + filePath: { header: 'PROJECT PATH' }, + } + ); } } @@ -167,11 +179,14 @@ export class DeployResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.blue('Deleted Source')); - this.ux.table(deletions, { - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); + this.ux.table( + deletions.map((entry) => ({ fullName: entry.fullName, type: entry.type, filePath: entry.filePath })), + { + fullName: { header: 'FULL NAME' }, + type: { header: 'TYPE' }, + filePath: { header: 'PROJECT PATH' }, + } + ); } protected displayFailures(): void { @@ -206,11 +221,23 @@ export class DeployResultFormatter extends ResultFormatter { if (failures.length) { this.ux.log(''); this.ux.styledHeader(chalk.red(`Component Failures [${failures.length}]`)); - this.ux.table(failures, { - problemType: { header: 'Type' }, - fullName: { header: 'Name' }, - error: { header: 'Problem' }, - }); + this.ux.table( + failures.map((entry: FileResponseFailure) => ({ + fullName: entry.fullName, + problemType: entry.problemType, + filePath: entry.filePath, + columnNumber: entry.columnNumber, + error: entry.error, + lineNumber: entry.lineNumber, + state: entry.state, + type: entry.type, + })), + { + problemType: { header: 'Type' }, + fullName: { header: 'Name' }, + error: { header: 'Problem' }, + } + ); this.ux.log(''); } } @@ -243,12 +270,20 @@ export class DeployResultFormatter extends ResultFormatter { this.ux.styledHeader( chalk.red(`Test Failures [${asString(this.result.response.details.runTestResult?.numFailures)}]`) ); - this.ux.table(tests, { - name: { header: 'Name' }, - methodName: { header: 'Method' }, - message: { header: 'Message' }, - stackTrace: { header: 'Stacktrace' }, - }); + this.ux.table( + tests.map((entry: Failures) => ({ + name: entry.name, + methodName: entry.methodName, + message: entry.message, + stackTrace: entry.stackTrace, + })), + { + name: { header: 'Name' }, + methodName: { header: 'Method' }, + message: { header: 'Message' }, + stackTrace: { header: 'Stacktrace' }, + } + ); } } @@ -258,10 +293,13 @@ export class DeployResultFormatter extends ResultFormatter { const tests = this.sortTestResults(success); this.ux.log(''); this.ux.styledHeader(chalk.green(`Test Success [${success.length}]`)); - this.ux.table(tests, { - name: { header: 'Name' }, - methodName: { header: 'Method' }, - }); + this.ux.table( + tests.map((test: Successes) => ({ name: test.name, methodName: test.methodName })), + { + name: { header: 'Name' }, + methodName: { header: 'Method' }, + } + ); } const codeCoverage = ensureArray(this.result?.response?.details?.runTestResult?.codeCoverage); @@ -270,11 +308,18 @@ export class DeployResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.blue('Apex Code Coverage')); - this.ux.table(coverage, { - name: { header: 'Name' }, - numLocations: { header: '% Covered' }, - lineNotCovered: { header: 'Uncovered Lines' }, - }); + this.ux.table( + coverage.map((cov) => ({ + name: cov.name, + numLocations: cov.numLocations, + lineNotCovered: cov.locationsNotCovered, + })), + { + name: { header: 'Name' }, + numLocations: { header: '% Covered' }, + lineNotCovered: { header: 'Uncovered Lines' }, + } + ); } } diff --git a/src/formatters/mdapi/convertResultFormatter.ts b/src/formatters/mdapi/convertResultFormatter.ts deleted file mode 100644 index 00c80d565..000000000 --- a/src/formatters/mdapi/convertResultFormatter.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as path from 'path'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; -import { ConvertResult } from '@salesforce/source-deploy-retrieve'; -import { ResultFormatter } from '../resultFormatter'; - -interface ConvertEntry { - fullName: string; - type: string; - filePath: string; - state: 'Add'; -} - -export type ConvertCommandResult = ConvertEntry[]; - -export class ConvertResultFormatter extends ResultFormatter { - protected result: ConvertResult; - private convertResults: ConvertCommandResult; - - public constructor(logger: Logger, ux: UX, result: ConvertResult) { - super(logger, ux); - this.result = result; - } - - public getJson(): ConvertCommandResult { - if (!this.convertResults) { - this.convertResults = []; - this.result?.converted.forEach((component) => { - if (component.xml) { - this.convertResults.push({ - fullName: component.fullName, - type: component.type.name, - filePath: path.relative('.', component.xml), - state: 'Add', - }); - } - if (component.content) { - this.convertResults.push({ - fullName: component.fullName, - type: component.type.name, - filePath: path.relative('.', component.content), - state: 'Add', - }); - } - }); - } - - return this.convertResults; - } - - public display(): void { - const convertData = this.getJson(); - if (convertData?.length) { - this.ux.table(convertData, { - state: { header: 'STATE' }, - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); - } else { - this.ux.log('No metadata found to convert'); - } - } -} diff --git a/src/formatters/mdapi/mdDeployAsyncResultFormatter.ts b/src/formatters/mdapi/mdDeployAsyncResultFormatter.ts index bb8f8b75f..2c7275d64 100644 --- a/src/formatters/mdapi/mdDeployAsyncResultFormatter.ts +++ b/src/formatters/mdapi/mdDeployAsyncResultFormatter.ts @@ -6,9 +6,10 @@ */ import { EOL } from 'os'; -import { UX } from '@salesforce/command'; -import { Logger, Messages } from '@salesforce/core'; + +import { Messages } from '@salesforce/core'; import { AsyncResult } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatterOptions } from '../resultFormatter'; import { DeployAsyncResultFormatter } from '../source/deployAsyncResultFormatter'; @@ -18,8 +19,8 @@ const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.deploy') export class MdDeployAsyncResultFormatter extends DeployAsyncResultFormatter { protected declare result: AsyncResult; - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, result: AsyncResult) { - super(logger, ux, options, result); + public constructor(ux: Ux, options: ResultFormatterOptions, result: AsyncResult) { + super(ux, options, result); this.result = result; } diff --git a/src/formatters/mdapi/mdDeployResultFormatter.ts b/src/formatters/mdapi/mdDeployResultFormatter.ts index e1f6270ef..92a6d2afe 100644 --- a/src/formatters/mdapi/mdDeployResultFormatter.ts +++ b/src/formatters/mdapi/mdDeployResultFormatter.ts @@ -7,31 +7,33 @@ import * as chalk from 'chalk'; import { getNumber } from '@salesforce/ts-types'; -import { UX } from '@salesforce/command'; -import { Logger, Messages, SfError } from '@salesforce/core'; +import { Messages, SfError } from '@salesforce/core'; import { DeployMessage, DeployResult, + Failures, MetadataApiDeployStatus, RequestStatus, + Successes, } from '@salesforce/source-deploy-retrieve'; import { ensureArray } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; import { CoverageResultsFileInfo, ResultFormatter, ResultFormatterOptions } from '../resultFormatter'; import { prepCoverageForDisplay } from '../../coverageUtils'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'md.deploy'); -export type MdDeployResult = MetadataApiDeployStatus & { +export type MdDeployResult = { coverage?: CoverageResultsFileInfo; junit?: string; -}; +} & MetadataApiDeployStatus; export class MdDeployResultFormatter extends ResultFormatter { protected result: DeployResult; - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, result: DeployResult) { - super(logger, ux, options); + public constructor(ux: Ux, options: ResultFormatterOptions, result: DeployResult) { + super(ux, options); this.result = result; } @@ -179,12 +181,20 @@ export class MdDeployResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.red(`Test Failures [${this.result.response.details.runTestResult?.numFailures}]`)); - this.ux.table(tests, { - name: { header: 'Name' }, - methodName: { header: 'Method' }, - message: { header: 'Message' }, - stackTrace: { header: 'Stacktrace' }, - }); + this.ux.table( + tests.map((test: Failures) => ({ + name: test.name, + methodName: test.methodName, + message: test.message, + stackTrace: test.stackTrace, + })), + { + name: { header: 'Name' }, + methodName: { header: 'Method' }, + message: { header: 'Message' }, + stackTrace: { header: 'Stacktrace' }, + } + ); } } @@ -194,10 +204,13 @@ export class MdDeployResultFormatter extends ResultFormatter { const tests = this.sortTestResults(success); this.ux.log(''); this.ux.styledHeader(chalk.green(`Test Success [${success.length}]`)); - this.ux.table(tests, { - name: { header: 'Name' }, - methodName: { header: 'Method' }, - }); + this.ux.table( + tests.map((test: Successes) => ({ name: test.name, methodName: test.methodName })), + { + name: { header: 'Name' }, + methodName: { header: 'Method' }, + } + ); } const codeCoverage = ensureArray(this.result?.response?.details?.runTestResult?.codeCoverage); @@ -207,11 +220,19 @@ export class MdDeployResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.blue('Apex Code Coverage')); - this.ux.table(coverage, { - name: { header: 'Name' }, - numLocations: { header: '% Covered' }, - lineNotCovered: { header: 'Uncovered Lines' }, - }); + // TODO: unsure about locationsNotCovered vs lineNotCovered + this.ux.table( + coverage.map((entry) => ({ + name: entry.name, + numLocations: entry.numLocations, + lineNotCovered: entry.locationsNotCovered, + })), + { + name: { header: 'Name' }, + numLocations: { header: '% Covered' }, + lineNotCovered: { header: 'Uncovered Lines' }, + } + ); } } diff --git a/src/formatters/mdapi/retrieveResultFormatter.ts b/src/formatters/mdapi/retrieveResultFormatter.ts index ba60c7fb0..9e486c71c 100644 --- a/src/formatters/mdapi/retrieveResultFormatter.ts +++ b/src/formatters/mdapi/retrieveResultFormatter.ts @@ -6,8 +6,6 @@ */ import { join, parse } from 'path'; import { blue } from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { getNumber } from '@salesforce/ts-types'; import { RetrieveResult, @@ -16,6 +14,7 @@ import { FileProperties, } from '@salesforce/source-deploy-retrieve'; import { ensureArray } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; import { RetrieveFormatter } from '../retrieveFormatter'; import { ResultFormatterOptions } from '../resultFormatter'; @@ -38,8 +37,8 @@ export interface RetrieveCommandAsyncResult { export class RetrieveResultFormatter extends RetrieveFormatter { protected zipFilePath: string; - public constructor(logger: Logger, ux: UX, public options: RetrieveResultFormatterOptions, result: RetrieveResult) { - super(logger, ux, options, result); + public constructor(ux: Ux, public options: RetrieveResultFormatterOptions, result: RetrieveResult) { + super(ux, options, result); this.options.zipFileName ??= 'unpackaged.zip'; this.zipFilePath = join(options.retrieveTargetDir, options.zipFileName); } diff --git a/src/formatters/progressFormatter.ts b/src/formatters/progressFormatter.ts index a43120768..b7d60eedb 100644 --- a/src/formatters/progressFormatter.ts +++ b/src/formatters/progressFormatter.ts @@ -5,16 +5,13 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; export abstract class ProgressFormatter { - public logger: Logger; - public ux: UX; + public ux: Ux; - public constructor(logger: Logger, ux: UX) { - this.logger = logger; + public constructor(ux: Ux) { this.ux = ux; } diff --git a/src/formatters/resultFormatter.ts b/src/formatters/resultFormatter.ts index b4f4744f1..b8608a0da 100644 --- a/src/formatters/resultFormatter.ts +++ b/src/formatters/resultFormatter.ts @@ -8,12 +8,11 @@ import * as path from 'path'; import * as fs from 'fs'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { Failures, FileProperties, FileResponse, Successes } from '@salesforce/source-deploy-retrieve'; import { getNumber } from '@salesforce/ts-types'; import * as chalk from 'chalk'; import { CoverageReporterOptions, DefaultReportOptions } from '@salesforce/apex-node'; +import { Ux } from '@salesforce/sf-plugins-core'; export interface ResultFormatterOptions { verbose?: boolean; @@ -30,15 +29,7 @@ export interface ResultFormatterOptions { export type CoverageResultsFileInfo = Record, string>; export abstract class ResultFormatter { - public logger: Logger; - public ux: UX; - public options: ResultFormatterOptions; - - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions = {}) { - this.logger = logger; - this.ux = ux; - this.options = options; - } + protected constructor(public ux: Ux, public options: ResultFormatterOptions = {}) {} // Command success is determined by the command so it can set the // exit code on the process, which is done before formatting. diff --git a/src/formatters/retrieveFormatter.ts b/src/formatters/retrieveFormatter.ts index e211899c5..c710c9748 100644 --- a/src/formatters/retrieveFormatter.ts +++ b/src/formatters/retrieveFormatter.ts @@ -6,7 +6,7 @@ */ import { yellow } from 'chalk'; -import { Logger, Messages, SfError } from '@salesforce/core'; +import { Messages, SfError } from '@salesforce/core'; import { get } from '@salesforce/ts-types'; import { MetadataApiRetrieveStatus, @@ -14,8 +14,9 @@ import { RetrieveMessage, RetrieveResult, } from '@salesforce/source-deploy-retrieve'; -import { UX } from '@salesforce/command'; + import { ensureArray } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter, ResultFormatterOptions } from './resultFormatter'; Messages.importMessagesDirectory(__dirname); @@ -25,8 +26,8 @@ export abstract class RetrieveFormatter extends ResultFormatter { protected result: MetadataApiRetrieveStatus; protected messages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); - public constructor(logger: Logger, ux: UX, public options: ResultFormatterOptions, result: RetrieveResult) { - super(logger, ux, options); + public constructor(ux: Ux, public options: ResultFormatterOptions, result: RetrieveResult) { + super(ux, options); // zipFile can become massive and unwieldy with JSON parsing/terminal output and, isn't useful delete result.response.zipFile; this.result = result.response; diff --git a/src/formatters/retrieveResultFormatter.ts b/src/formatters/retrieveResultFormatter.ts index c5285822a..6666f4286 100644 --- a/src/formatters/retrieveResultFormatter.ts +++ b/src/formatters/retrieveResultFormatter.ts @@ -6,8 +6,6 @@ */ import { blue } from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; import { getNumber } from '@salesforce/ts-types'; import { RetrieveResult, @@ -17,6 +15,7 @@ import { RequestStatus, RetrieveMessage, } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { RetrieveFormatter } from './retrieveFormatter'; import { ResultFormatterOptions } from './resultFormatter'; @@ -29,19 +28,19 @@ export interface RetrieveResultFormatterOptions extends ResultFormatterOptions { packages?: PackageRetrieval[]; } -export interface RetrieveCommandResult { +export type RetrieveCommandResult = { inboundFiles: FileResponse[]; packages: PackageRetrieval[]; warnings: RetrieveMessage[]; response: MetadataApiRetrieveStatus; -} +}; export class RetrieveResultFormatter extends RetrieveFormatter { protected packages: PackageRetrieval[] = []; protected fileResponses: FileResponse[]; - public constructor(logger: Logger, ux: UX, options: RetrieveResultFormatterOptions, result: RetrieveResult) { - super(logger, ux, options, result); + public constructor(ux: Ux, options: RetrieveResultFormatterOptions, result: RetrieveResult) { + super(ux, options, result); this.fileResponses = result?.getFileResponses ? result.getFileResponses() : []; this.packages = options.packages || []; } @@ -99,10 +98,19 @@ export class RetrieveResultFormatter extends RetrieveFormatter { private displaySuccesses(retrievedFiles: FileResponse[]): void { this.sortFileResponses(retrievedFiles); this.asRelativePaths(retrievedFiles); - this.ux.table(retrievedFiles, { - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); + this.ux.table( + retrievedFiles.map((retrieved) => ({ + fullName: retrieved.fullName, + type: retrieved.type, + filePath: retrieved.filePath, + state: retrieved.state, + })), + { + fullName: { header: 'FULL NAME' }, + type: { header: 'TYPE' }, + filePath: { header: 'PROJECT PATH' }, + state: { header: 'STATE' }, + } + ); } } diff --git a/src/formatters/source/deleteResultFormatter.ts b/src/formatters/source/deleteResultFormatter.ts deleted file mode 100644 index 0431b487e..000000000 --- a/src/formatters/source/deleteResultFormatter.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import { DeployMessage, DeployResult, FileResponse } from '@salesforce/source-deploy-retrieve'; -import { UX } from '@salesforce/command'; -import { Logger } from '@salesforce/core'; -import * as chalk from 'chalk'; -import { ensureArray } from '@salesforce/kit'; -import { DeployCommandResult, DeployResultFormatter } from '../deployResultFormatter'; -import { ResultFormatterOptions } from '../resultFormatter'; - -export class DeleteResultFormatter extends DeployResultFormatter { - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, result?: DeployResult) { - super(logger, ux, options, result); - } - - /** - * Get the JSON output from the DeployResult. - * - * @returns a JSON formatted result matching the provided type. - */ - public getJson(): DeployCommandResult { - const json = this.getResponse() as DeployCommandResult; - json.deletedSource = this.fileResponses; // to match toolbelt json output - json.outboundFiles = []; // to match toolbelt version - json.deletes = [Object.assign({}, this.getResponse())]; // to match toolbelt version - - return json; - } - - public displayNoResultsFound(): void { - // matches toolbelt - this.ux.styledHeader(chalk.blue('Deleted Source')); - this.ux.log('No results found'); - } - - protected displaySuccesses(): void { - if (this.isSuccess()) { - const successes: Array = []; - const fileResponseSuccesses: Map = new Map(); - - if (this.fileResponses?.length) { - const fileResponses: FileResponse[] = []; - this.fileResponses.map((f: FileResponse) => { - fileResponses.push(f); - fileResponseSuccesses.set(`${f.type}#${f.fullName}`, f); - }); - this.sortFileResponses(fileResponses); - this.asRelativePaths(fileResponses); - successes.push(...fileResponses); - } - - const deployMessages = ensureArray(this.result?.response?.details?.componentSuccesses).filter( - (item) => !item.fileName.includes('package.xml') - ); - if (deployMessages.length >= successes.length) { - // if there's additional successes in the API response, find the success and add it to the output - deployMessages.map((deployMessage) => { - if (!fileResponseSuccesses.has(`${deployMessage.componentType}#${deployMessage.fullName}`)) { - successes.push( - Object.assign(deployMessage, { - type: deployMessage.componentType, - }) - ); - } - }); - } - - this.ux.log(''); - this.ux.styledHeader(chalk.blue('Deleted Source')); - this.ux.table(successes, { - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); - } - } -} diff --git a/src/formatters/source/deployAsyncResultFormatter.ts b/src/formatters/source/deployAsyncResultFormatter.ts index 008fa3a1a..05c6386d2 100644 --- a/src/formatters/source/deployAsyncResultFormatter.ts +++ b/src/formatters/source/deployAsyncResultFormatter.ts @@ -6,10 +6,11 @@ */ import { EOL } from 'os'; -import { UX } from '@salesforce/command'; -import { Logger, Messages } from '@salesforce/core'; + +import { Messages } from '@salesforce/core'; import { cloneJson } from '@salesforce/kit'; import { AsyncResult } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter, ResultFormatterOptions } from '../resultFormatter'; Messages.importMessagesDirectory(__dirname); @@ -33,8 +34,8 @@ export interface DeployAsyncStatus { export class DeployAsyncResultFormatter extends ResultFormatter { protected result: AsyncResult; - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, result: AsyncResult) { - super(logger, ux, options); + public constructor(ux: Ux, options: ResultFormatterOptions, result: AsyncResult) { + super(ux, options); this.result = result; } diff --git a/src/formatters/source/pullFormatter.ts b/src/formatters/source/pullFormatter.ts index a5506d82d..057c8264e 100644 --- a/src/formatters/source/pullFormatter.ts +++ b/src/formatters/source/pullFormatter.ts @@ -6,8 +6,8 @@ */ import { blue, yellow } from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger, Messages, SfError } from '@salesforce/core'; + +import { Messages, SfError } from '@salesforce/core'; import { ensureArray } from '@salesforce/kit'; import { get, getNumber, getString } from '@salesforce/ts-types'; import { @@ -17,15 +17,11 @@ import { RetrieveMessage, RetrieveResult, } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter, ResultFormatterOptions } from '../resultFormatter'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'pull', [ - 'retrievedSourceWarningsHeader', - 'retrievedSourceHeader', - 'retrieveTimeout', - 'NoResultsFound', -]); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'pull'); export type PullResponse = { pulledSource: Array> }; @@ -35,13 +31,12 @@ export class PullResultFormatter extends ResultFormatter { protected warnings: RetrieveMessage[]; public constructor( - logger: Logger, - ux: UX, + ux: Ux, options: ResultFormatterOptions, retrieveResult: RetrieveResult, deleteResult: FileResponse[] = [] ) { - super(logger, ux, options); + super(ux, options); this.result = retrieveResult; this.fileResponses = (retrieveResult?.getFileResponses ? retrieveResult.getFileResponses() : []).concat( deleteResult @@ -120,12 +115,20 @@ export class PullResultFormatter extends ResultFormatter { private displaySuccesses(retrievedFiles: FileResponse[]): void { this.sortFileResponses(retrievedFiles); this.asRelativePaths(retrievedFiles); - this.ux.table(retrievedFiles, { - state: { header: 'STATE' }, - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); + this.ux.table( + retrievedFiles.map((entry) => ({ + state: entry.state, + fullName: entry.fullName, + type: entry.type, + filePath: entry.filePath, + })), + { + state: { header: 'STATE' }, + fullName: { header: 'FULL NAME' }, + type: { header: 'TYPE' }, + filePath: { header: 'PROJECT PATH' }, + } + ); } private displayErrors(): void { diff --git a/src/formatters/source/pushResultFormatter.ts b/src/formatters/source/pushResultFormatter.ts index 61e89903b..26478f86e 100644 --- a/src/formatters/source/pushResultFormatter.ts +++ b/src/formatters/source/pushResultFormatter.ts @@ -6,11 +6,10 @@ */ import { relative, resolve as pathResolve } from 'path'; import * as chalk from 'chalk'; -import { UX } from '@salesforce/command'; -import { Logger, Messages, SfError } from '@salesforce/core'; + +import { Messages, SfError } from '@salesforce/core'; import { ComponentStatus, - DeployMessage, DeployResult, FileResponse, MetadataResolver, @@ -19,6 +18,7 @@ import { } from '@salesforce/source-deploy-retrieve'; import { isString } from '@salesforce/ts-types'; import { ensureArray } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter, ResultFormatterOptions } from '../resultFormatter'; Messages.importMessagesDirectory(__dirname); @@ -33,14 +33,13 @@ export class PushResultFormatter extends ResultFormatter { protected fileResponses: FileResponse[]; protected replacements: Map; public constructor( - logger: Logger, - ux: UX, + ux: Ux, options: ResultFormatterOptions, protected results: DeployResult[], // if your push included deletes that are bundle subcomponents, we'll need to add those deletes to the results even though they aren't included in fileResponses protected deletes: string[] = [] ) { - super(logger, ux, options); + super(ux, options); this.fileResponses = this.correctFileResponses(); this.replacements = mergeReplacements(results); } @@ -51,12 +50,13 @@ export class PushResultFormatter extends ResultFormatter { * @returns a JSON formatted result matching the provided type. */ public getJson(): PushResponse { - // throws a particular json structure. commandName property will be appended by sfdxCommand when this throws + // throws a particular json structure. if (process.exitCode !== 0) { const error = new SfError(messages.getMessage('sourcepushFailed', ['']), 'DeployFailed', [], process.exitCode); const errorData = this.fileResponses.filter((fileResponse) => fileResponse.state === ComponentStatus.Failed); error.setData(errorData); error['result'] = errorData; + error['commandName'] = 'Push'; // partial success if (process.exitCode === 69) { error['partialSuccess'] = this.fileResponses.filter( @@ -72,7 +72,7 @@ export class PushResultFormatter extends ResultFormatter { return { pushedSource: toReturn.map(({ state, fullName, type, filePath }) => ({ state, fullName, type, filePath })), ...(!this.isQuiet() && this.replacements.size ? { replacements: Object.fromEntries(this.replacements) } : {}), - }; + } as PushResponse; } /** @@ -163,12 +163,20 @@ export class PushResultFormatter extends ResultFormatter { this.ux.log(''); this.ux.styledHeader(chalk.blue('Pushed Source')); - this.ux.table(successes, { - state: { header: 'STATE' }, - fullName: { header: 'FULL NAME' }, - type: { header: 'TYPE' }, - filePath: { header: 'PROJECT PATH' }, - }); + this.ux.table( + successes.map((entry) => ({ + state: entry.state, + fullName: entry.fullName, + type: entry.type, + filePath: entry.filePath, + })), + { + state: { header: 'STATE' }, + fullName: { header: 'FULL NAME' }, + type: { header: 'TYPE' }, + filePath: { header: 'PROJECT PATH' }, + } + ); } } @@ -190,7 +198,7 @@ export class PushResultFormatter extends ResultFormatter { } protected displayFailures(): void { - const failures: Array = []; + const failures = []; const fileResponseFailures: Map = new Map(); if (this.fileResponses?.length) { @@ -240,7 +248,7 @@ export class PushResultFormatter extends ResultFormatter { try { return resolver.getComponentsFromPath(filename); } catch (e) { - this.logger.warn(`unable to resolve ${filename}`); + this.ux.warn(`unable to resolve ${filename}`); return []; } } diff --git a/src/formatters/source/statusFormatter.ts b/src/formatters/source/statusFormatter.ts index 81ebadef8..4497e93e0 100644 --- a/src/formatters/source/statusFormatter.ts +++ b/src/formatters/source/statusFormatter.ts @@ -4,17 +4,18 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { UX } from '@salesforce/command'; -import { Logger, Messages } from '@salesforce/core'; + +import { Messages } from '@salesforce/core'; +import { Ux } from '@salesforce/sf-plugins-core'; import { ResultFormatter, ResultFormatterOptions } from '../resultFormatter'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'status', ['humanSuccess', 'noResults']); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'status'); type StatusActualState = 'Deleted' | 'Add' | 'Changed' | 'Unchanged'; type StatusOrigin = 'Local' | 'Remote'; type StatusStateString = `${StatusOrigin} ${StatusActualState}` | `${StatusOrigin} ${StatusActualState} (Conflict)`; -export interface StatusResult { +export type StatusResult = { state: StatusStateString; fullName: string; type: string; @@ -23,7 +24,7 @@ export interface StatusResult { conflict?: boolean; actualState?: StatusActualState; origin: StatusOrigin; -} +}; // sort order is state, type, fullname const rowSortFunction = (a: StatusResult, b: StatusResult): number => { @@ -37,8 +38,8 @@ const rowSortFunction = (a: StatusResult, b: StatusResult): number => { }; export class StatusFormatter extends ResultFormatter { - public constructor(logger: Logger, ux: UX, options: ResultFormatterOptions, private statusRows: StatusResult[]) { - super(logger, ux, options); + public constructor(ux: Ux, options: ResultFormatterOptions, private statusRows: StatusResult[]) { + super(ux, options); } public getJson(): StatusResult[] { diff --git a/src/sourceCommand.ts b/src/sourceCommand.ts index f513aa01c..008dc9522 100644 --- a/src/sourceCommand.ts +++ b/src/sourceCommand.ts @@ -7,42 +7,28 @@ import { dirname, resolve, extname } from 'path'; import * as fs from 'fs'; -import { SfdxCommand } from '@salesforce/command'; -import { Messages, Lifecycle, SfError } from '@salesforce/core'; +import { Messages, SfError } from '@salesforce/core'; import { ComponentSet } from '@salesforce/source-deploy-retrieve'; -import { get, getBoolean, getString, Optional } from '@salesforce/ts-types'; +import { getString, Optional } from '@salesforce/ts-types'; import { ux } from '@oclif/core'; +import { SfCommand } from '@salesforce/sf-plugins-core'; import { EnsureFsFlagOptions, FsError, ProgressBar } from './types'; Messages.importMessagesDirectory(__dirname); -const messages = Messages.load('@salesforce/plugin-source', 'flags.validation', [ - 'InvalidFlagPath', - 'expectedDirectory', - 'expectedFile', - 'notFound', -]); +const messages = Messages.loadMessages('@salesforce/plugin-source', 'flags.validation'); // TODO: use messages for tracking version compatibility errors // Messages.importMessagesDirectory(__dirname); // const messages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); -export abstract class SourceCommand extends SfdxCommand { +export abstract class SourceCommand extends SfCommand { public static readonly DEFAULT_WAIT_MINUTES = 33; protected progressBar?: ProgressBar; - protected lifecycle = Lifecycle.getInstance(); protected componentSet?: ComponentSet; - protected isJsonOutput(): boolean { - return getBoolean(this.flags, 'json', false); - } - - protected getFlag(flagName: string, defaultVal?: unknown): T { - return get(this.flags, flagName, defaultVal) as T; - } - protected initProgressBar(): void { - this.logger.debug('initializing progress bar'); + this.debug('initializing progress bar'); this.progressBar = ux.progress({ format: 'SOURCE PROGRESS | {bar} | {value}/{total} Components', barCompleteChar: '\u2588', diff --git a/src/stash.ts b/src/stash.ts index 898f6606a..d29851eea 100644 --- a/src/stash.ts +++ b/src/stash.ts @@ -53,7 +53,6 @@ export class Stash { 'force:source:deploy': Stash.KEYS.SOURCE_DEPLOY, 'force:source:deploy:cancel': Stash.KEYS.SOURCE_DEPLOY, 'force:source:deploy:report': Stash.KEYS.SOURCE_DEPLOY, - 'force:source:delete': Stash.KEYS.SOURCE_DEPLOY, 'force:mdapi:retrieve': Stash.KEYS.MDAPI_RETRIEVE, 'force:mdapi:retrieve:report': Stash.KEYS.MDAPI_RETRIEVE, 'force:mdapi:beta:retrieve': Stash.KEYS.MDAPI_RETRIEVE, @@ -88,7 +87,7 @@ export class Stash { public static getKey(commandId: string): StashKey { const key = Stash.keyMap[commandId] as StashKey; if (!key) { - const messages = Messages.load('@salesforce/plugin-source', 'stash', ['InvalidStashKey']); + const messages = Messages.loadMessages('@salesforce/plugin-source', 'stash'); throw new SfError(messages.getMessage('InvalidStashKey', [commandId]), 'InvalidStashKey'); } return key; @@ -139,7 +138,7 @@ export class Stash { const stashFilePath = Stash.instance?.getPath(); const corruptFilePath = `${stashFilePath}_corrupted_${Date.now()}`; fs.renameSync(stashFilePath, corruptFilePath); - const messages = Messages.load('@salesforce/plugin-source', 'stash', ['InvalidStashKey']); + const messages = Messages.loadMessages('@salesforce/plugin-source', 'stash'); throw new SfError( `${messages.getMessage('InvalidStashKey', [corruptFilePath])}\n\n${error.message}`, 'InvalidStashFile', diff --git a/src/trackingFunctions.ts b/src/trackingFunctions.ts index 10332fa8b..de45f3180 100644 --- a/src/trackingFunctions.ts +++ b/src/trackingFunctions.ts @@ -5,7 +5,7 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import * as path from 'path'; -import { UX } from '@salesforce/command'; + import { ChangeResult, getTrackingFileVersion, @@ -21,19 +21,20 @@ import { FileResponse, RetrieveResult, } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'tracking'); interface TrackingSetupRequest extends SourceTrackingOptions { ignoreConflicts: boolean; - ux: UX; + ux: Ux; commandName: string; } interface TrackingUpdateRequest { tracking: SourceTracking; result: DeployResult | RetrieveResult; - ux: UX; + ux: Ux; /** * We don't want to get the fileResponses if there have been deletes (SDR will throw) * You can also pass this in if your command already ran getFileResponses and you want to avoid the perf hit from doing it twice @@ -41,12 +42,12 @@ interface TrackingUpdateRequest { fileResponses?: FileResponse[]; } -interface ConflictResponse { +type ConflictResponse = { state: 'Conflict'; fullName: string; type: string; filePath: string; -} +}; /** * Check if any conflicts exist in a specific component set. * If conflicts exist, this will output the table and throw @@ -58,7 +59,7 @@ export const filterConflictsByComponentSet = async ({ }: { tracking: SourceTracking; components: ComponentSet; - ux: UX; + ux: Ux; }): Promise => { const filteredConflicts = (await tracking.getConflicts()).filter((cr) => components.has({ fullName: cr.name, type: cr.type }) @@ -114,13 +115,13 @@ export const updateTracking = async ({ tracking, result, ux, fileResponses }: Tr if (!result) { return; } - ux.startSpinner('Updating source tracking'); + ux.spinner.start('Updating source tracking'); const successes = (fileResponses ?? result.getFileResponses()).filter( (fileResponse) => fileResponse.state !== ComponentStatus.Failed ); if (!successes.length) { - ux.stopSpinner(); + ux.spinner.stop(); return; } @@ -139,10 +140,10 @@ export const updateTracking = async ({ tracking, result, ux, fileResponses }: Tr ), ]); - ux.stopSpinner(); + ux.spinner.stop(); }; -const writeConflictTable = (conflicts: ConflictResponse[], ux: UX): void => { +const writeConflictTable = (conflicts: ConflictResponse[], ux: Ux): void => { ux.table(conflicts, { state: { header: 'STATE' }, fullName: { header: 'FULL NAME' }, @@ -158,7 +159,7 @@ const writeConflictTable = (conflicts: ConflictResponse[], ux: UX): void => { * @param ux * @param message */ -const processConflicts = (conflicts: ChangeResult[], ux: UX, message: string): void => { +const processConflicts = (conflicts: ChangeResult[], ux: Ux, message: string): void => { if (conflicts.length === 0) { return; } diff --git a/test/commands/mdapi/cancel.test.ts b/test/commands/mdapi/cancel.test.ts index a85e2d3e9..b47eaf9ed 100644 --- a/test/commands/mdapi/cancel.test.ts +++ b/test/commands/mdapi/cancel.test.ts @@ -8,11 +8,12 @@ import { join } from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { fromStub, spyMethod, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { ConfigFile, Org, SfProject } from '@salesforce/core'; -import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; +import { spyMethod, stubMethod } from '@salesforce/ts-sinon'; +import { ConfigFile } from '@salesforce/core'; + import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; +import { stubSfCommandUx, stubUx } from '@salesforce/sf-plugins-core'; import { Cancel } from '../../../src/commands/force/mdapi/deploy/cancel'; import { DeployCancelResultFormatter } from '../../../src/formatters/deployCancelResultFormatter'; import { DeployCommandResult } from '../../../src/formatters/deployResultFormatter'; @@ -20,8 +21,11 @@ import { getDeployResult } from '../source/deployResponses'; import { Stash } from '../../../src/stash'; describe('force:mdapi:deploy:cancel', () => { - const sandbox = sinon.createSandbox(); - const username = 'cancel-test@org.com'; + Cancel.id = 'force:mdapi:deploy:cancel'; + + const $$ = new TestContext(); + let testOrg: MockTestOrgData; + const defaultDir = join('my', 'default', 'package'); const stashedDeployId = 'IMA000STASHID'; @@ -29,116 +33,83 @@ describe('force:mdapi:deploy:cancel', () => { const expectedResults = deployResult.response as DeployCommandResult; expectedResults.deployedSource = deployResult.getFileResponses(); expectedResults.outboundFiles = []; - expectedResults.deploys = [deployResult.response]; // Stubs - const oclifConfigStub = fromStub(stubInterface(sandbox)); - let checkDeployStatusStub: sinon.SinonStub; + let pollStub: sinon.SinonStub; let cancelStub: sinon.SinonStub; - let uxLogStub: sinon.SinonStub; - - class TestCancel extends Cancel { - public async runIt() { - await this.init(); - // oclif would normally populate this, but UT don't have it - this.id ??= 'force:mdapi:deploy:cancel'; - return this.run(); - } - public setOrg(org: Org) { - this.org = org; - } - public setProject(project: SfProject) { - this.project = project; - } - - // eslint-disable-next-line class-methods-use-this - public createDeploy(): MetadataApiDeploy { - cancelStub = sandbox.stub(MetadataApiDeploy.prototype, 'cancel'); - return MetadataApiDeploy.prototype; - } - } - - const runCancelCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 - const cmd = new TestCancel(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getUniquePackageDirectories: () => [{ fullPath: defaultDir }], - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - getConnection: () => ({ - metadata: { - checkDeployStatus: checkDeployStatusStub, - }, - }), - }) - ); - cmd.setOrg(orgStub); - }); - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); - stubMethod(sandbox, ConfigFile.prototype, 'readSync'); - stubMethod(sandbox, ConfigFile.prototype, 'get').returns({ jobid: stashedDeployId }); - checkDeployStatusStub = sandbox.stub().resolves(expectedResults); + let sfCommandUxStubs: ReturnType; + let stubUxStubs: ReturnType; - return cmd.runIt(); - }; + beforeEach(async () => { + // to suppress the output of the ux in test results + sfCommandUxStubs = stubSfCommandUx($$.SANDBOX); + // because we're constructing a Ux and passing it to the formatter + stubUxStubs = stubUx($$.SANDBOX); + // stash uses the ID. Oclif doesn't have it set on static run, so we add it manually + testOrg = new MockTestOrgData(); + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); - afterEach(() => { - sandbox.restore(); + stubMethod($$.SANDBOX, ConfigFile.prototype, 'get').returns({ jobid: stashedDeployId }); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + pollStub = $$.SANDBOX.stub(Cancel.prototype, 'poll').resolves({ response: expectedResults }); + stubMethod($$.SANDBOX, Cancel.prototype, 'createDeploy').returns(MetadataApiDeploy.prototype); + cancelStub = $$.SANDBOX.stub(MetadataApiDeploy.prototype, 'cancel'); + $$.setConfigStubContents('sfdx-project.json', { + packageDirectories: [{ fullPath: defaultDir, path: defaultDir, name: 'default' }], + }); }); it('should use stashed deploy ID', async () => { - const getStashSpy = spyMethod(sandbox, Stash, 'get'); - const result = await runCancelCmd(['--json']); + const getStashSpy = spyMethod($$.SANDBOX, Stash, 'get'); + const result = await Cancel.run(['--json']); + expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(true); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(stashedDeployId); + expect(pollStub.firstCall.args[1]).to.equal(stashedDeployId); expect(cancelStub.calledOnce).to.equal(true); + expect(sfCommandUxStubs.log.callCount).to.equal(0); + expect(stubUxStubs.log.callCount).to.equal(0); }); it('should display stashed deploy ID', async () => { - const result = await runCancelCmd([]); + const result = await Cancel.run([]); expect(result).to.deep.equal(expectedResults); - expect(uxLogStub.firstCall.args[0]).to.contain(stashedDeployId); }); it('should use the jobid flag', async () => { - const getStashSpy = spyMethod(sandbox, Stash, 'get'); - const result = await runCancelCmd(['--json', '--jobid', expectedResults.id]); + const getStashSpy = spyMethod($$.SANDBOX, Stash, 'get'); + const result = await Cancel.run(['--json', '--jobid', expectedResults.id]); + expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(false); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(expectedResults.id); + expect(pollStub.firstCall.args[1]).to.equal(expectedResults.id); expect(cancelStub.calledOnce).to.equal(true); }); it('should display the jobid flag', async () => { - const result = await runCancelCmd(['--jobid', expectedResults.id]); + const result = await Cancel.run(['--jobid', expectedResults.id]); expect(result).to.deep.equal(expectedResults); - expect(uxLogStub.firstCall.args[0]).to.contain(expectedResults.id); + expect(stubUxStubs.log.args.flat()).to.deep.include(`Successfully canceled ${expectedResults.id}`); }); it('should display output with no --json', async () => { - const displayStub = sandbox.stub(DeployCancelResultFormatter.prototype, 'display'); - const getJsonStub = sandbox.stub(DeployCancelResultFormatter.prototype, 'getJson'); - await runCancelCmd([]); + const displayStub = $$.SANDBOX.stub(DeployCancelResultFormatter.prototype, 'display'); + const getJsonStub = $$.SANDBOX.stub(DeployCancelResultFormatter.prototype, 'getJson'); + await Cancel.run([]); expect(displayStub.calledOnce).to.equal(true); expect(getJsonStub.calledOnce).to.equal(true); - expect(uxLogStub.called).to.equal(true); }); it('should NOT display output with --json', async () => { - const displayStub = sandbox.stub(DeployCancelResultFormatter.prototype, 'display'); - const getJsonStub = sandbox.stub(DeployCancelResultFormatter.prototype, 'getJson'); - await runCancelCmd(['--json']); + const displayStub = $$.SANDBOX.stub(DeployCancelResultFormatter.prototype, 'display'); + const getJsonStub = $$.SANDBOX.stub(DeployCancelResultFormatter.prototype, 'getJson'); + await Cancel.run(['--json']); + expect(displayStub.calledOnce).to.equal(false); expect(getJsonStub.calledOnce).to.equal(true); - expect(uxLogStub.called).to.equal(false); + expect(sfCommandUxStubs.log.callCount).to.equal(0); + expect(stubUxStubs.log.callCount).to.equal(0); }); }); diff --git a/test/commands/mdapi/convert.test.ts b/test/commands/mdapi/convert.test.ts deleted file mode 100644 index acb866003..000000000 --- a/test/commands/mdapi/convert.test.ts +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as fs from 'fs'; -import { join, resolve } from 'path'; -import * as sinon from 'sinon'; -import { assert, expect } from 'chai'; -import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; -import { SfProject } from '@salesforce/core'; -import { ComponentSetBuilder, MetadataConverter } from '@salesforce/source-deploy-retrieve'; -import { Convert } from '../../../src/commands/force/mdapi/convert'; -import { FsError } from '../../../src/types'; - -const testConvertResult = { - converted: [ - { - fullName: 'TestProductController', - type: { - name: 'ApexClass', - }, - xml: join('myPkg', 'src', 'classes', 'TestProductController.cls-meta.xml'), - }, - { - fullName: 'TestProductController', - type: { - name: 'ApexClass', - }, - content: join('myPkg', 'src', 'classes', 'TestProductController.cls'), - }, - ], -}; - -const expectedConvertResult = [ - { - fullName: 'TestProductController', - type: 'ApexClass', - filePath: join('myPkg', 'src', 'classes', 'TestProductController.cls-meta.xml'), - state: 'Add', - }, - { - fullName: 'TestProductController', - type: 'ApexClass', - filePath: join('myPkg', 'src', 'classes', 'TestProductController.cls'), - state: 'Add', - }, -]; - -const commandName = 'mdapi:convert'; - -describe(`force:${commandName}`, () => { - const sandbox = sinon.createSandbox(); - - const oclifConfigStub = fromStub(stubInterface(sandbox)); - - const defaultDir = join('my', 'default', 'package'); - let uxLogStub: sinon.SinonStub; - let uxTableStub: sinon.SinonStub; - let uxStartSpinnerStub: sinon.SinonStub; - let uxStopSpinnerStub: sinon.SinonStub; - let fsStatStub: sinon.SinonStub; - let fsMkdirStub: sinon.SinonStub; - let convertStub: sinon.SinonStub; - let csBuilderStub: sinon.SinonStub; - - class TestConvert extends Convert { - public async runIt() { - await this.init(); - return this.run(); - } - public setProject(project: SfProject) { - this.project = project; - } - } - - const runConvertCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 - const cmd = new TestConvert(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getDefaultPackage: () => ({ path: defaultDir }), - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg'); - - return cmd.runIt(); - }; - - beforeEach(() => { - fsMkdirStub = sandbox.stub(fs, 'mkdirSync'); - fsStatStub = sandbox.stub(fs, 'statSync'); - - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); - uxTableStub = stubMethod(sandbox, UX.prototype, 'table'); - uxStartSpinnerStub = stubMethod(sandbox, UX.prototype, 'startSpinner'); - uxStopSpinnerStub = stubMethod(sandbox, UX.prototype, 'stopSpinner'); - - convertStub = sandbox.stub(MetadataConverter.prototype, 'convert'); - csBuilderStub = sandbox.stub(ComponentSetBuilder, 'build'); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should error when rootdir is not a directory', async () => { - const fileName = ' imaFile.txt '; // spaces ensure trim() is done - const trimmedFileName = fileName.trim(); - fsStatStub.returns({ isDirectory: () => false }); - try { - await runConvertCmd(['--rootdir', fileName]); - assert(false, `expected ${commandName} to error`); - } catch (e: unknown) { - expect((e as Error).name).to.equal('InvalidFlagPath'); - expect((e as Error).message).to.include(trimmedFileName); - } - }); - - it('should error when outputdir is not a directory', async () => { - const rootdir = 'rootdir'; - const resolvedRootDir = resolve(rootdir); - const fileName = ' imaFile.txt '; // spaces ensure trim() is done - const trimmedFileName = fileName.trim(); - const resolvedFilePath = resolve(trimmedFileName); - fsStatStub.withArgs(resolvedRootDir).returns({ isDirectory: () => true }); - fsStatStub.withArgs(resolvedFilePath).returns({ isDirectory: () => false }); - try { - await runConvertCmd(['--rootdir', rootdir, '--outputdir', fileName]); - assert(false, `expected ${commandName} to error`); - } catch (e: unknown) { - expect((e as Error).name).to.equal('InvalidFlagPath'); - expect((e as Error).message).to.include(trimmedFileName); - expect((e as Error).message).to.include('outputdir'); - } - }); - - it('should error when metadatapath does not exist', async () => { - const rootdir = 'rootdir'; - const resolvedRootDir = resolve(rootdir); - const fileName = ' nonexistant.txt '; // spaces ensure trim() is done - const trimmedFileName = fileName.trim(); - const resolvedFilePath = resolve(trimmedFileName); - const resolvedOutputDir = resolve(defaultDir); - fsStatStub.withArgs(defaultDir).returns({ isDirectory: () => true }); - fsStatStub.withArgs(resolvedRootDir).returns({ isDirectory: () => true }); - fsStatStub.withArgs(resolvedOutputDir).returns({ isDirectory: () => true }); - const err = new Error('') as FsError; - err.code = 'ENOENT'; - fsStatStub.withArgs(resolvedFilePath).throws(err); - try { - await runConvertCmd(['--rootdir', rootdir, '--metadatapath', fileName]); - assert(false, `expected ${commandName} to error`); - } catch (e: unknown) { - expect((e as Error).name).to.equal('InvalidFlagPath'); - expect((e as Error).message).to.include(trimmedFileName); - expect((e as Error).message).to.include('metadatapath'); - expect(fsMkdirStub.called).to.be.false; - } - }); - - it('should error when manifest does not exist', async () => { - const rootdir = 'rootdir'; - const resolvedRootDir = resolve(rootdir); - const fileName = ' nonexistant.txt '; // spaces ensure trim() is done - const trimmedFileName = fileName.trim(); - const resolvedFilePath = resolve(trimmedFileName); - const resolvedOutputDir = resolve(defaultDir); - fsStatStub.withArgs(defaultDir).returns({ isDirectory: () => true }); - fsStatStub.withArgs(resolvedRootDir).returns({ isDirectory: () => true }); - fsStatStub.withArgs(resolvedOutputDir).returns({ isDirectory: () => true }); - const err = new Error('') as FsError; - err.code = 'ENOENT'; - fsStatStub.withArgs(resolvedFilePath).throws(err); - try { - await runConvertCmd(['--rootdir', rootdir, '--manifest', fileName]); - assert(false, `expected ${commandName} to error`); - } catch (e: unknown) { - expect((e as Error).name).to.equal('InvalidFlagPath'); - expect((e as Error).message).to.include(trimmedFileName); - expect((e as Error).message).to.include('manifest'); - expect(fsMkdirStub.called).to.be.false; - } - }); - - it('should create the outputdir when it does not exist', async () => { - const rootdir = 'rootdir'; - const resolvedRootDir = resolve(rootdir); - const dirName = 'mdGoesHere'; - const resolvedOutputDir = resolve(dirName); - fsStatStub.withArgs(resolvedRootDir).returns({ isDirectory: () => true }); - const err = new Error('') as FsError; - err.code = 'ENOENT'; - fsStatStub.withArgs(resolvedOutputDir).throws(err); - csBuilderStub.resolves({ - getSourceComponents: () => ({ toArray: () => [] }), - }); - const result = await runConvertCmd(['--rootdir', 'rootdir', '--outputdir', resolvedOutputDir]); - expect(result).to.deep.equal([]); - expect(fsMkdirStub.called).to.be.true; - expect(fsMkdirStub.firstCall.args[0]).to.equal(resolvedOutputDir); - }); - - it('should return an empty array when no metadata converted (json)', async () => { - csBuilderStub.resolves({ - getSourceComponents: () => ({ toArray: () => [] }), - }); - fsStatStub.returns({ isDirectory: () => true }); - const result = await runConvertCmd(['--rootdir', 'rootdir', '--json']); - expect(result).to.deep.equal([]); - expect(convertStub.called).to.be.false; - expect(uxStartSpinnerStub.called).to.be.false; - expect(uxStopSpinnerStub.called).to.be.false; - expect(uxLogStub.called).to.be.false; - expect(uxTableStub.called).to.be.false; - }); - - it('should report when no metadata converted (display)', async () => { - csBuilderStub.resolves({ - getSourceComponents: () => ({ toArray: () => [] }), - }); - fsStatStub.returns({ isDirectory: () => true }); - const result = await runConvertCmd(['--rootdir', 'rootdir']); - expect(result).to.deep.equal([]); - expect(convertStub.called).to.be.false; - expect(uxStartSpinnerStub.called).to.be.false; - expect(uxStopSpinnerStub.called).to.be.false; - expect(uxLogStub.calledWith('No metadata found to convert')).to.be.true; - expect(uxTableStub.called).to.be.false; - }); - - it('should return an array of metadata converted (json)', async () => { - const mockCompSet = { - getSourceComponents: () => ({ toArray: () => ['firstComp', 'secondComp'] }), - }; - fsStatStub.returns({ isDirectory: () => true }); - csBuilderStub.resolves(mockCompSet); - convertStub.resolves(testConvertResult); - const result = await runConvertCmd(['--rootdir', 'rootdir', '--json']); - expect(result).to.deep.equal(expectedConvertResult); - expect(convertStub.called).to.be.true; - expect(convertStub.firstCall.args[0]).to.equal(mockCompSet); - expect(convertStub.firstCall.args[1]).to.equal('source'); - expect(uxStartSpinnerStub.called).to.be.true; - expect(uxStopSpinnerStub.called).to.be.true; - expect(uxLogStub.called).to.be.false; - expect(uxTableStub.called).to.be.false; - }); - - it('should report a table of metadata converted (display)', async () => { - const mockCompSet = { - getSourceComponents: () => ({ toArray: () => ['firstComp', 'secondComp'] }), - }; - fsStatStub.returns({ isDirectory: () => true }); - csBuilderStub.resolves(mockCompSet); - convertStub.resolves(testConvertResult); - const result = await runConvertCmd(['--rootdir', 'rootdir']); - expect(result).to.deep.equal(expectedConvertResult); - expect(convertStub.called).to.be.true; - expect(convertStub.firstCall.args[0]).to.equal(mockCompSet); - expect(convertStub.firstCall.args[1]).to.equal('source'); - expect(uxStartSpinnerStub.called).to.be.true; - expect(uxStartSpinnerStub.firstCall.args[0]).to.equal('Converting 2 metadata components'); - expect(uxStopSpinnerStub.called).to.be.true; - expect(uxLogStub.called).to.be.false; - expect(uxTableStub.called).to.be.true; - }); -}); diff --git a/test/commands/mdapi/retrieve.test.ts b/test/commands/mdapi/retrieve.test.ts index 0d25f1019..4f0ab407d 100644 --- a/test/commands/mdapi/retrieve.test.ts +++ b/test/commands/mdapi/retrieve.test.ts @@ -9,19 +9,23 @@ import * as fs from 'fs'; import * as path from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Lifecycle, Org, SfProject } from '@salesforce/core'; +import { Lifecycle, SfProject } from '@salesforce/core'; import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; + import { ComponentSetBuilder, ComponentSetOptions, RetrieveOptions } from '@salesforce/source-deploy-retrieve'; import { Duration } from '@salesforce/kit'; +import { SfCommand, Ux } from '@salesforce/sf-plugins-core'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; import { Retrieve } from '../../../src/commands/force/mdapi/retrieve'; import { Stash, StashData } from '../../../src/stash'; import { getRetrieveResult } from '../source/retrieveResponses'; describe('force:mdapi:retrieve', () => { - const sandbox = sinon.createSandbox(); - const username = 'retrieve-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'retrieve-test@org.com'; const packageXml = 'package.xml'; const retrievetargetdir = path.resolve('retrieve-target-dir'); const oclifConfigStub = fromStub(stubInterface(sandbox)); @@ -35,8 +39,8 @@ describe('force:mdapi:retrieve', () => { let retrieveStub: sinon.SinonStub; let pollStub: sinon.SinonStub; let lifecycleEmitStub: sinon.SinonStub; - let stopSpinnerStub: sinon.SinonStub; let uxLogStub: sinon.SinonStub; + let sfCommandLogStub: sinon.SinonStub; let uxStyledHeaderStub: sinon.SinonStub; let uxTableStub: sinon.SinonStub; let stashSetStub: sinon.SinonStub; @@ -45,50 +49,29 @@ describe('force:mdapi:retrieve', () => { class TestRetrieve extends Retrieve { public async runIt() { - await this.init(); // oclif would normally populate this, but UT don't have it this.id ??= 'force:mdapi:retrieve'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:mdpi:retrive'; + await this.init(); return this.run(); } - public setOrg(org: Org) { - this.org = org; - } - public setUx(ux: UX) { - this.ux = ux; - } } const runRetrieveCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestRetrieve(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - }) - ); - cmd.setOrg(orgStub); - }); - stopSpinnerStub = stubMethod(sandbox, UX.prototype, 'stopSpinner'); - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); - uxStyledHeaderStub = stubMethod(sandbox, UX.prototype, 'styledHeader'); - uxTableStub = stubMethod(sandbox, UX.prototype, 'table'); - cmd.setUx( - fromStub( - stubInterface(sandbox, { - stopSpinner: stopSpinnerStub, - log: uxLogStub, - styledHeader: uxStyledHeaderStub, - table: uxTableStub, - }) - ) - ); + uxLogStub = stubMethod(sandbox, Ux.prototype, 'log'); + sfCommandLogStub = stubMethod(sandbox, SfCommand.prototype, 'log'); + uxStyledHeaderStub = stubMethod(sandbox, Ux.prototype, 'styledHeader'); + uxTableStub = stubMethod(sandbox, Ux.prototype, 'table'); return cmd.runIt(); }; - beforeEach(() => { + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); sandbox.stub(fs, 'mkdirSync'); fsStatStub = sandbox.stub(fs, 'statSync'); fsStatStub.withArgs(retrievetargetdir).returns({ isDirectory: () => true }); @@ -115,6 +98,7 @@ describe('force:mdapi:retrieve', () => { }); afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -135,7 +119,7 @@ describe('force:mdapi:retrieve', () => { // Ensure ComponentSet.retrieve() args const ensureRetrieveArgs = (overrides?: Partial) => { const defaultRetrieveArgs = { - usernameOrConnection: username, + usernameOrConnection: testOrg.username, output: path.resolve(retrievetargetdir), format: 'metadata', packageOptions: undefined, @@ -220,7 +204,7 @@ describe('force:mdapi:retrieve', () => { it('should pass along packagenames', async () => { const packagenames = 'foo,bar'; - const result = await runRetrieveCmd(['--retrievetargetdir', retrievetargetdir, '-p', packagenames, '--json']); + const result = await runRetrieveCmd(['--retrievetargetdir', retrievetargetdir, '-p', 'foo', '-p', 'bar', '--json']); expect(result).to.deep.equal(expectedDefaultResult); ensureCreateComponentSetArgs({ sourcepath: undefined, packagenames: packagenames.split(',') }); ensureRetrieveArgs({ packageOptions: packagenames.split(',') }); @@ -288,8 +272,8 @@ describe('force:mdapi:retrieve', () => { const result = await runRetrieveCmd(['-r', retrievetargetdir]); expect(result).to.deep.equal(expectedDefaultResult); expect(uxLogStub.called).to.be.true; - expect(uxLogStub.firstCall.args[0]).to.equal(`Retrieve ID: ${expectedDefaultResult.id}`); - expect(uxLogStub.secondCall.args[0]).to.contain('Wrote retrieve zip to'); + expect(sfCommandLogStub.firstCall.args[0]).to.equal(`Retrieve ID: ${expectedDefaultResult.id}`); + expect(uxLogStub.firstCall.args[0]).to.contain('Wrote retrieve zip to'); expect(uxStyledHeaderStub.called).to.be.false; expect(uxTableStub.called).to.be.false; }); @@ -298,8 +282,8 @@ describe('force:mdapi:retrieve', () => { const result = await runRetrieveCmd(['-r', retrievetargetdir, '--verbose']); expect(result).to.deep.equal(expectedDefaultResult); expect(uxLogStub.called).to.be.true; - expect(uxLogStub.firstCall.args[0]).to.equal(`Retrieve ID: ${expectedDefaultResult.id}`); - expect(uxLogStub.secondCall.args[0]).to.contain('Wrote retrieve zip to'); + expect(sfCommandLogStub.firstCall.args[0]).to.equal(`Retrieve ID: ${expectedDefaultResult.id}`); + expect(uxLogStub.firstCall.args[0]).to.contain('Wrote retrieve zip to'); expect(uxStyledHeaderStub.called).to.be.true; expect(uxTableStub.called).to.be.true; expect(uxStyledHeaderStub.firstCall.args[0]).to.contain('Components Retrieved'); @@ -321,7 +305,5 @@ describe('force:mdapi:retrieve', () => { ensureStashSet(); expect(fsStatStub.called).to.be.true; expect(pollStub.called, 'should not poll for status with --wait 0').to.be.false; - expect(stopSpinnerStub.called).to.be.true; - expect(stopSpinnerStub.firstCall.args[0]).to.equal('queued'); }); }); diff --git a/test/commands/mdapi/retrieveReport.test.ts b/test/commands/mdapi/retrieveReport.test.ts index 6126c021d..0544ddcf6 100644 --- a/test/commands/mdapi/retrieveReport.test.ts +++ b/test/commands/mdapi/retrieveReport.test.ts @@ -9,18 +9,21 @@ import * as fs from 'fs'; import * as path from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Org } from '@salesforce/core'; import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; + import { MetadataApiRetrieve } from '@salesforce/source-deploy-retrieve'; +import { SfCommand, Ux } from '@salesforce/sf-plugins-core'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; import { Report } from '../../../src/commands/force/mdapi/retrieve/report'; import { Stash } from '../../../src/stash'; import { getRetrieveResult, getRetrieveResponse } from '../source/retrieveResponses'; describe('force:mdapi:retrieve:report', () => { - const sandbox = sinon.createSandbox(); - const username = 'report-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'report-test@org.com'; const retrievetargetdir = path.resolve('retrieve-target-dir'); const oclifConfigStub = fromStub(stubInterface(sandbox)); const retrieveResult = getRetrieveResult('success'); @@ -37,8 +40,8 @@ describe('force:mdapi:retrieve:report', () => { let checkStatusStub: sinon.SinonStub; let postStub: sinon.SinonStub; let pollStatusStub: sinon.SinonStub; - let stopSpinnerStub: sinon.SinonStub; let uxLogStub: sinon.SinonStub; + let sfCommandLogStub: sinon.SinonStub; let uxStyledHeaderStub: sinon.SinonStub; let uxTableStub: sinon.SinonStub; let stashSetStub: sinon.SinonStub; @@ -47,50 +50,30 @@ describe('force:mdapi:retrieve:report', () => { class TestReport extends Report { public async runIt() { - await this.init(); - // set a Command.id for use with Stash + // oclif would normally populate this, but UT don't have it this.id ??= 'force:mdapi:retrieve:report'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:mdapi:retrieve:report'; + await this.init(); return this.run(); } - public setOrg(org: Org) { - this.org = org; - } - public setUx(ux: UX) { - this.ux = ux; - } } const runReportCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestReport(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - }) - ); - cmd.setOrg(orgStub); - }); - stopSpinnerStub = stubMethod(sandbox, UX.prototype, 'stopSpinner'); - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); - uxStyledHeaderStub = stubMethod(sandbox, UX.prototype, 'styledHeader'); - uxTableStub = stubMethod(sandbox, UX.prototype, 'table'); - cmd.setUx( - fromStub( - stubInterface(sandbox, { - stopSpinner: stopSpinnerStub, - log: uxLogStub, - styledHeader: uxStyledHeaderStub, - table: uxTableStub, - }) - ) - ); + uxLogStub = stubMethod(sandbox, Ux.prototype, 'log'); + sfCommandLogStub = stubMethod(sandbox, SfCommand.prototype, 'log'); + uxStyledHeaderStub = stubMethod(sandbox, Ux.prototype, 'styledHeader'); + uxTableStub = stubMethod(sandbox, SfCommand.prototype, 'table'); return cmd.runIt(); }; - beforeEach(() => { + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); + sandbox.stub(fs, 'mkdirSync'); fsStatStub = sandbox.stub(fs, 'statSync'); fsStatStub.returns({ isDirectory: () => true }); @@ -102,6 +85,7 @@ describe('force:mdapi:retrieve:report', () => { }); afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -187,9 +171,7 @@ describe('force:mdapi:retrieve:report', () => { expect(uxLogStub.called).to.be.true; expect(uxLogStub.firstCall.args[0]).to.equal(`Wrote retrieve zip to ${defaultZipFilePath}`); expect(uxStyledHeaderStub.called).to.be.true; - expect(uxTableStub.called).to.be.true; expect(uxStyledHeaderStub.firstCall.args[0]).to.contain('Components Retrieved'); - expect(uxTableStub.firstCall.args[0]).to.deep.equal(expectedDefaultResult.fileProperties); }); it('should return an async result with --wait 0', async () => { @@ -209,7 +191,7 @@ describe('force:mdapi:retrieve:report', () => { expect(postStub.called).to.be.false; expect(fsStatStub.called).to.be.true; expect(pollStatusStub.called, 'should not poll for status with --wait 0').to.be.false; - expect(stopSpinnerStub.called).to.be.true; + expect(sfCommandLogStub.called).to.be.true; }); it('should return a normal result with --wait 0', async () => { @@ -223,6 +205,5 @@ describe('force:mdapi:retrieve:report', () => { expect(postStub.called).to.be.true; expect(fsStatStub.called).to.be.true; expect(pollStatusStub.called, 'should not poll for status with --wait 0').to.be.false; - expect(stopSpinnerStub.called).to.be.true; }); }); diff --git a/test/commands/source/cancel.test.ts b/test/commands/source/cancel.test.ts index 6a72decfc..da47eb279 100644 --- a/test/commands/source/cancel.test.ts +++ b/test/commands/source/cancel.test.ts @@ -9,10 +9,11 @@ import { join } from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; import { fromStub, spyMethod, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { ConfigFile, Org, SfProject } from '@salesforce/core'; +import { ConfigFile, SfProject } from '@salesforce/core'; import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; +import { Ux } from '@salesforce/sf-plugins-core'; import { Cancel } from '../../../src/commands/force/source/deploy/cancel'; import { DeployCancelResultFormatter } from '../../../src/formatters/deployCancelResultFormatter'; import { DeployCommandResult } from '../../../src/formatters/deployResultFormatter'; @@ -20,8 +21,10 @@ import { Stash } from '../../../src/stash'; import { getDeployResult } from './deployResponses'; describe('force:source:deploy:cancel', () => { - const sandbox = sinon.createSandbox(); - const username = 'cancel-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'cancel-test@org.com'; const defaultDir = join('my', 'default', 'package'); const stashedDeployId = 'IMA000STASHID'; @@ -33,23 +36,19 @@ describe('force:source:deploy:cancel', () => { // Stubs const oclifConfigStub = fromStub(stubInterface(sandbox)); - let checkDeployStatusStub: sinon.SinonStub; + let pollStub: sinon.SinonStub; let cancelStub: sinon.SinonStub; let uxLogStub: sinon.SinonStub; class TestCancel extends Cancel { public async runIt() { - await this.init(); // oclif would normally populate this, but UT don't have it this.id ??= 'force:source:deploy:cancel'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:source:deploy:cancel'; + await this.init(); return this.run(); } - public setOrg(org: Org) { - this.org = org; - } - public setProject(project: SfProject) { - this.project = project; - } // eslint-disable-next-line class-methods-use-this public createDeploy(): MetadataApiDeploy { @@ -59,38 +58,26 @@ describe('force:source:deploy:cancel', () => { } const runCancelCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestCancel(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getUniquePackageDirectories: () => [{ fullPath: defaultDir }], - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - getConnection: () => ({ - metadata: { - checkDeployStatus: checkDeployStatusStub, - }, - }), - }) - ); - cmd.setOrg(orgStub); - }); - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); - stubMethod(sandbox, ConfigFile.prototype, 'readSync'); + cmd.project = SfProject.getInstance(); + sandbox.stub(cmd.project, 'getUniquePackageDirectories').returns([{ fullPath: defaultDir, path: '', name: '' }]); + + uxLogStub = stubMethod(sandbox, Ux.prototype, 'log'); stubMethod(sandbox, ConfigFile.prototype, 'get').returns({ jobid: stashedDeployId }); - checkDeployStatusStub = sandbox.stub().resolves(expectedResults); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + pollStub = sandbox.stub(cmd, 'poll').resolves({ response: expectedResults }); return cmd.runIt(); }; + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); + }); + afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -99,14 +86,13 @@ describe('force:source:deploy:cancel', () => { const result = await runCancelCmd(['--json']); expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(true); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(stashedDeployId); + expect(pollStub.firstCall.args[1]).to.equal(stashedDeployId); expect(cancelStub.calledOnce).to.equal(true); }); it('should display stashed deploy ID', async () => { const result = await runCancelCmd([]); expect(result).to.deep.equal(expectedResults); - expect(uxLogStub.firstCall.args[0]).to.contain(stashedDeployId); }); it('should use the jobid flag', async () => { @@ -114,7 +100,7 @@ describe('force:source:deploy:cancel', () => { const result = await runCancelCmd(['--json', '--jobid', expectedResults.id]); expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(false); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(expectedResults.id); + expect(pollStub.firstCall.args[1]).to.equal(expectedResults.id); expect(cancelStub.calledOnce).to.equal(true); }); @@ -130,7 +116,6 @@ describe('force:source:deploy:cancel', () => { await runCancelCmd([]); expect(displayStub.calledOnce).to.equal(true); expect(getJsonStub.calledOnce).to.equal(true); - expect(uxLogStub.called).to.equal(true); }); it('should NOT display output with --json', async () => { diff --git a/test/commands/source/convert.test.ts b/test/commands/source/convert.test.ts deleted file mode 100644 index 38dc30da2..000000000 --- a/test/commands/source/convert.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import { join, resolve } from 'path'; -import { ComponentSetBuilder, ComponentSetOptions, MetadataConverter } from '@salesforce/source-deploy-retrieve'; -import * as sinon from 'sinon'; -import { expect } from 'chai'; -import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { Config } from '@oclif/core'; -import { SfProject } from '@salesforce/core'; -import { Convert } from '../../../src/commands/force/source/convert'; - -describe('force:source:convert', () => { - const sandbox = sinon.createSandbox(); - - let buildComponentSetStub: sinon.SinonStub; - - const defaultDir = join('my', 'default', 'package'); - const myApp = join('new', 'package', 'directory'); - const packageXml = 'package.xml'; - const oclifConfigStub = fromStub(stubInterface(sandbox)); - let resolveProjectConfigStub: sinon.SinonStub; - - class TestConvert extends Convert { - public async runIt() { - await this.init(); - return this.run(); - } - public setProject(project: SfProject) { - this.project = project; - } - } - - const runConvertCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 - const cmd = new TestConvert(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getDefaultPackage: () => ({ path: defaultDir }), - getUniquePackageDirectories: () => [{ fullPath: defaultDir }], - resolveProjectConfig: resolveProjectConfigStub, - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg'); - return cmd.runIt(); - }; - - // Ensure correct ComponentSetBuilder options - const ensureCreateComponentSetArgs = (overrides?: Partial) => { - const defaultArgs = { - sourcepath: [], - manifest: undefined, - metadata: undefined, - sourceapiversion: undefined, - }; - const expectedArgs = { ...defaultArgs, ...overrides }; - - expect(buildComponentSetStub.calledOnce).to.equal(true); - expect(buildComponentSetStub.firstCall.args[0]).to.deep.equal(expectedArgs); - }; - - beforeEach(() => { - resolveProjectConfigStub = sandbox.stub(); - sandbox.stub(MetadataConverter.prototype, 'convert').resolves({ packagePath: 'temp' }); - buildComponentSetStub = stubMethod(sandbox, ComponentSetBuilder, 'build').resolves({ - deploy: sinon.stub(), - getPackageXml: () => packageXml, - }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should pass along sourcepath', async () => { - const sourcepath = 'somepath'; - const result = await runConvertCmd(['--sourcepath', sourcepath, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ sourcepath: [sourcepath] }); - }); - - it('should pass along sourceApiVersion', async () => { - const sourceApiVersion = '50.0'; - resolveProjectConfigStub.resolves({ sourceApiVersion }); - const result = await runConvertCmd(['--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ - sourcepath: [defaultDir], - sourceapiversion: sourceApiVersion, - }); - }); - - it('should call default package dir if no args', async () => { - const result = await runConvertCmd(['--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ sourcepath: [defaultDir] }); - }); - - it('should call with metadata', async () => { - const metadata = 'ApexClass'; - const result = await runConvertCmd(['--metadata', metadata, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ - metadata: { - metadataEntries: [metadata], - directoryPaths: [defaultDir], - }, - }); - }); - - it('should call with package.xml', async () => { - const result = await runConvertCmd(['--manifest', packageXml, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ - manifest: { - manifestPath: packageXml, - directoryPaths: [defaultDir], - }, - }); - }); - - it('should call root dir with rootdir flag', async () => { - const result = await runConvertCmd(['--rootdir', myApp, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ sourcepath: [myApp] }); - }); - - describe('rootdir should be overwritten by any other flag', () => { - it('sourcepath', async () => { - const result = await runConvertCmd(['--rootdir', myApp, '--sourcepath', defaultDir, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ sourcepath: [defaultDir] }); - }); - - it('metadata', async () => { - const metadata = 'ApexClass,CustomObject'; - const result = await runConvertCmd(['--rootdir', myApp, '--metadata', metadata, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ - metadata: { - metadataEntries: metadata.split(','), - directoryPaths: [defaultDir], - }, - }); - }); - - it('package', async () => { - const result = await runConvertCmd(['--rootdir', myApp, '--manifest', packageXml, '--json']); - expect(result).to.deep.equal({ location: resolve('temp') }); - ensureCreateComponentSetArgs({ - manifest: { - manifestPath: packageXml, - directoryPaths: [defaultDir], - }, - }); - }); - }); -}); diff --git a/test/commands/source/delete.test.ts b/test/commands/source/delete.test.ts deleted file mode 100644 index 69efffafa..000000000 --- a/test/commands/source/delete.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as fs from 'fs'; -import { join } from 'path'; -import * as sinon from 'sinon'; -import { expect } from 'chai'; -import { - ComponentSet, - ComponentSetBuilder, - ComponentSetOptions, - SourceComponent, - RegistryAccess, -} from '@salesforce/source-deploy-retrieve'; -import { Lifecycle, Org, SfProject } from '@salesforce/core'; -import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; -import { Delete } from '../../../src/commands/force/source/delete'; -import { exampleDeleteResponse, exampleSourceComponent } from './testConsts'; - -const fsPromises = fs.promises; -const registry = new RegistryAccess(); - -describe('force:source:delete', () => { - const sandbox = sinon.createSandbox(); - const username = 'delete-test@org.com'; - const defaultPackagePath = 'defaultPackagePath'; - let confirm = true; - - const oclifConfigStub = fromStub(stubInterface(sandbox)); - - // Stubs - let buildComponentSetStub: sinon.SinonStub; - let lifecycleEmitStub: sinon.SinonStub; - let resolveProjectConfigStub: sinon.SinonStub; - let fsUnlink: sinon.SinonStub; - let moveToStashStub: sinon.SinonStub; - let restoreFromStashStub: sinon.SinonStub; - let deleteStashStub: sinon.SinonStub; - - class TestDelete extends Delete { - public async runIt() { - await this.init(); - // oclif would normally populate this, but UT don't have it - this.id ??= 'force:source:delete'; - return this.run(); - } - public setOrg(org: Org) { - this.org = org; - } - public setProject(project: SfProject) { - this.project = project; - } - } - - const runDeleteCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 - const cmd = new TestDelete(params, oclifConfigStub); - stubMethod(sandbox, SfProject, 'resolveProjectPath').resolves(join('path', 'to', 'package')); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getDefaultPackage: () => ({ fullPath: defaultPackagePath }), - getUniquePackageDirectories: () => [{ fullPath: defaultPackagePath }], - resolveProjectConfig: resolveProjectConfigStub, - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - }) - ); - cmd.setOrg(orgStub); - }); - stubMethod(sandbox, UX.prototype, 'log'); - stubMethod(sandbox, ComponentSet.prototype, 'deploy').resolves({ - id: '123', - pollStatus: () => exampleDeleteResponse, - }); - stubMethod(sandbox, cmd, 'handlePrompt').returns(confirm); - fsUnlink = stubMethod(sandbox, fsPromises, 'unlink').resolves(true); - moveToStashStub = stubMethod(sandbox, cmd, 'moveFileToStash'); - restoreFromStashStub = stubMethod(sandbox, cmd, 'restoreFileFromStash'); - deleteStashStub = stubMethod(sandbox, cmd, 'deleteStash'); - - return cmd.runIt(); - }; - - beforeEach(() => { - resolveProjectConfigStub = sandbox.stub(); - buildComponentSetStub = stubMethod(sandbox, ComponentSetBuilder, 'build').resolves({ - toArray: () => [new SourceComponent(exampleSourceComponent)], - }); - lifecycleEmitStub = sandbox.stub(Lifecycle.prototype, 'emit'); - }); - - afterEach(() => { - sandbox.restore(); - }); - - // Ensure SourceCommand.createComponentSet() args - const ensureCreateComponentSetArgs = (overrides?: Partial) => { - const defaultArgs = { - sourcepath: undefined, - metadata: undefined, - apiversion: undefined, - sourceapiversion: undefined, - }; - const expectedArgs = { ...defaultArgs, ...overrides }; - - expect(buildComponentSetStub.calledOnce).to.equal(true); - expect(buildComponentSetStub.firstCall.args[0]).to.deep.equal(expectedArgs); - }; - - // Ensure Lifecycle hooks are called properly - const ensureHookArgs = () => { - const failureMsg = 'Lifecycle.emit() should be called for predeploy and postdeploy'; - expect(lifecycleEmitStub.calledTwice, failureMsg).to.equal(true); - expect(lifecycleEmitStub.firstCall.args[0]).to.equal('predeploy'); - expect(lifecycleEmitStub.secondCall.args[0]).to.equal('postdeploy'); - }; - - it('should pass along sourcepath', async () => { - const sourcepath = ['somepath']; - stubMethod(sandbox, fs, 'statSync').returns({ isDirectory: () => false }); - await runDeleteCmd(['--sourcepath', sourcepath[0], '--json', '-r']); - ensureCreateComponentSetArgs({ sourcepath }); - ensureHookArgs(); - // deleting the component and its xml - expect(fsUnlink.callCount).to.equal(2); - }); - - it('should pass along metadata', async () => { - const metadata = ['ApexClass:MyClass']; - stubMethod(sandbox, fs, 'statSync').returns({ isDirectory: () => false }); - await runDeleteCmd(['--metadata', metadata[0], '--json', '-r']); - ensureCreateComponentSetArgs({ - metadata: { - metadataEntries: metadata, - directoryPaths: [defaultPackagePath], - }, - }); - ensureHookArgs(); - }); - - it('should pass along apiversion', async () => { - const metadata = ['ApexClass:MyClass']; - stubMethod(sandbox, fs, 'statSync').returns({ isDirectory: () => false }); - - await runDeleteCmd(['--metadata', metadata[0], '--json', '-r', '--apiversion', '52.0']); - ensureCreateComponentSetArgs({ - metadata: { - metadataEntries: metadata, - directoryPaths: [defaultPackagePath], - }, - apiversion: '52.0', - }); - ensureHookArgs(); - }); - - it('should pass along sourceapiversion', async () => { - const sourceApiVersion = '50.0'; - const metadata = ['ApexClass:MyClass']; - - resolveProjectConfigStub.resolves({ sourceApiVersion }); - stubMethod(sandbox, fs, 'statSync').returns({ isDirectory: () => false }); - - await runDeleteCmd(['--metadata', metadata[0], '--json', '-r']); - ensureCreateComponentSetArgs({ - sourceapiversion: sourceApiVersion, - metadata: { - metadataEntries: metadata, - directoryPaths: [defaultPackagePath], - }, - }); - ensureHookArgs(); - }); - - const stubLWC = (): string => { - buildComponentSetStub.restore(); - const comp = new SourceComponent({ - name: 'mylwc', - type: registry.getTypeByName('LightningComponentBundle'), - }); - stubMethod(sandbox, ComponentSetBuilder, 'build').resolves({ - toArray: () => [comp], - }); - const helperPath = join('dreamhouse-lwc', 'force-app', 'main', 'default', 'lwc', 'mylwc', 'helper.js'); - - stubMethod(sandbox, comp, 'walkContent').returns([ - join('dreamhouse-lwc', 'force-app', 'main', 'default', 'lwc', 'mylwc', 'mylwc.js'), - helperPath, - ]); - - stubMethod(sandbox, fs, 'statSync').returns({ isDirectory: () => false }); - return helperPath; - }; - - it('will use stash and delete stash upon successful delete', async () => { - const sourcepath = stubLWC(); - const result = await runDeleteCmd(['--sourcepath', sourcepath, '--json', '-r']); - // successful delete will move files to the stash, delete the stash, and won't restore from it - expect(moveToStashStub.calledOnce).to.be.true; - expect(deleteStashStub.calledOnce).to.be.true; - expect(restoreFromStashStub.called).to.be.false; - expect(result.deletedSource).to.deep.equal([ - { - filePath: sourcepath, - fullName: join('mylwc', 'helper.js'), - state: 'Deleted', - type: 'LightningComponentBundle', - }, - ]); - }); - - it('restores from stash during aborted delete', async () => { - const sourcepath = stubLWC(); - - confirm = false; - const result = await runDeleteCmd(['--sourcepath', sourcepath, '--json', '-r']); - // aborted delete will move files to the stash, and restore from it - expect(moveToStashStub.calledOnce).to.be.true; - expect(deleteStashStub.called).to.be.false; - expect(restoreFromStashStub.calledOnce).to.be.true; - // ensure JSON output from aborted delete - expect(result).to.deep.equal({ - result: { - deletedSource: [], - deletes: [{}], - outboundFiles: [], - }, - status: 0, - }); - }); -}); diff --git a/test/commands/source/deploy.test.ts b/test/commands/source/deploy.test.ts index ebb58181a..2f8e36849 100644 --- a/test/commands/source/deploy.test.ts +++ b/test/commands/source/deploy.test.ts @@ -10,9 +10,10 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; import { ComponentSetBuilder, ComponentSetOptions, MetadataApiDeployOptions } from '@salesforce/source-deploy-retrieve'; import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { ConfigAggregator, Lifecycle, Messages, Org, SfProject } from '@salesforce/core'; -import { UX } from '@salesforce/command'; +import { ConfigAggregator, Lifecycle, Messages, SfProject } from '@salesforce/core'; import { Config } from '@oclif/core'; +import { SfCommand } from '@salesforce/sf-plugins-core'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; import { Deploy } from '../../../src/commands/force/source/deploy'; import { DeployCommandResult, DeployResultFormatter } from '../../../src/formatters/deployResultFormatter'; import { @@ -27,8 +28,10 @@ import { exampleSourceComponent } from './testConsts'; Messages.importMessagesDirectory(__dirname); describe('force:source:deploy', () => { - const sandbox = sinon.createSandbox(); - const username = 'deploy-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'deploy-test@org.com'; const packageXml = 'package.xml'; const defaultDir = join('my', 'default', 'package'); const oclifConfigStub = fromStub(stubInterface(sandbox)); @@ -70,49 +73,36 @@ describe('force:source:deploy', () => { class TestDeploy extends Deploy { public async runIt() { - await this.init(); // oclif would normally populate this, but UT don't have it this.id ??= 'force:source:deploy'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:source:deploy'; + await this.init(); return this.run(); } - public setOrg(org: Org) { - this.org = org; - } - public setProject(project: SfProject) { - this.project = project; - } } - const runDeployCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 + const runDeployCmd = async (params: string[], options?: { sourceApiVersion?: string }) => { const cmd = new TestDeploy(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getUniquePackageDirectories: () => [{ fullPath: defaultDir }], - resolveProjectConfig: resolveProjectConfigStub, - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - }) - ); - cmd.setOrg(orgStub); - }); + cmd.project = SfProject.getInstance(); + sandbox.stub(cmd.project, 'getDefaultPackage').returns({ name: '', path: '', fullPath: defaultDir }); + sandbox.stub(cmd.project, 'getUniquePackageDirectories').returns([{ fullPath: defaultDir, path: '', name: '' }]); + sandbox.stub(cmd.project, 'getPackageDirectories').returns([{ fullPath: defaultDir, path: '', name: '' }]); + sandbox.stub(cmd.project, 'resolveProjectConfig').resolves({ sourceApiVersion: options?.sourceApiVersion }); + initProgressBarStub = stubMethod(sandbox, cmd, 'initProgressBar'); progressBarStub = stubMethod(sandbox, DeployProgressBarFormatter.prototype, 'progress'); progressStatusStub = stubMethod(sandbox, DeployProgressStatusFormatter.prototype, 'progress'); - stubMethod(sandbox, UX.prototype, 'log'); + stubMethod(sandbox, SfCommand.prototype, 'log'); stubMethod(sandbox, Deploy.prototype, 'deployRecentValidation').resolves({}); formatterDisplayStub = stubMethod(sandbox, DeployResultFormatter.prototype, 'display'); return cmd.runIt(); }; - beforeEach(() => { + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); + resolveProjectConfigStub = sandbox.stub(); pollStub = sandbox.stub().resolves(deployResult); deployStub = sandbox.stub().resolves({ @@ -128,6 +118,7 @@ describe('force:source:deploy', () => { }); afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -149,7 +140,7 @@ describe('force:source:deploy', () => { // Ensure ComponentSet.deploy() args const ensureDeployArgs = (overrides?: Partial) => { const expectedDeployArgs = { - usernameOrConnection: username, + usernameOrConnection: testOrg.username, apiOptions: { ignoreWarnings: false, rollbackOnError: true, @@ -245,7 +236,7 @@ describe('force:source:deploy', () => { const sourceApiVersion = '50.0'; resolveProjectConfigStub.resolves({ sourceApiVersion }); const manifest = 'package.xml'; - const result = await runDeployCmd(['--manifest', manifest, '--json']); + const result = await runDeployCmd(['--manifest', manifest, '--json'], { sourceApiVersion }); expect(result).to.deep.equal(expectedResults); ensureCreateComponentSetArgs({ sourceapiversion: sourceApiVersion, @@ -384,7 +375,6 @@ describe('force:source:deploy', () => { it('should use SOAP by default', async () => { delete process.env.SFDX_REST_DEPLOY; const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -395,7 +385,6 @@ describe('force:source:deploy', () => { try { process.env.SFDX_REST_DEPLOY = 'false'; const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -409,7 +398,6 @@ describe('force:source:deploy', () => { try { process.env.SFDX_REST_DEPLOY = 'true'; const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0]], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -423,7 +411,6 @@ describe('force:source:deploy', () => { try { process.env.SFDX_REST_DEPLOY = 'true'; const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -435,7 +422,6 @@ describe('force:source:deploy', () => { it('should use SOAP from flag', async () => { const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -446,7 +432,6 @@ describe('force:source:deploy', () => { stubMethod(sandbox, ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); stubMethod(sandbox, ConfigAggregator.prototype, 'getPropertyValue').returns('false'); const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method @@ -459,7 +444,6 @@ describe('force:source:deploy', () => { stubMethod(sandbox, ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); stubMethod(sandbox, ConfigAggregator.prototype, 'getPropertyValue').returns('false'); const sourcepath = ['somepath']; - // @ts-expect-error type mismatch between oclif/core v1 and v2 const cmd = new TestDeploy(['--sourcepath', sourcepath[0], '--soapdeploy'], oclifConfigStub); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private method diff --git a/test/commands/source/deployCommand.test.ts b/test/commands/source/deployCommand.test.ts index dfeb81995..423eeee58 100644 --- a/test/commands/source/deployCommand.test.ts +++ b/test/commands/source/deployCommand.test.ts @@ -5,24 +5,8 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import * as path from 'path'; -import { SfError } from '@salesforce/core'; -import { assert, expect } from 'chai'; -import { DeployCommand, getCoverageFormattersOptions } from '../../../src/deployCommand'; - -describe('test static method for valid deploy IDs', () => { - it('valid deployId returns true', () => { - expect(DeployCommand.isValidDeployId('0Af000000012345')).to.be.true; - }); - - it('valid deployId throws', () => { - try { - DeployCommand.isValidDeployId('00D000000012345'); - assert.fail('should have thrown'); - } catch (e) { - expect((e as SfError).name).to.equal('invalidDeployId'); - } - }); -}); +import { expect } from 'chai'; +import { getCoverageFormattersOptions } from '../../../src/deployCommand'; describe('coverage functions', () => { describe('getCoverageFormattersOptions', () => { diff --git a/test/commands/source/progressBarFormatter.test.ts b/test/commands/source/progressBarFormatter.test.ts index d80980e44..52aa4f37c 100644 --- a/test/commands/source/progressBarFormatter.test.ts +++ b/test/commands/source/progressBarFormatter.test.ts @@ -5,20 +5,19 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import { EventEmitter } from 'events'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; import { spyMethod } from '@salesforce/ts-sinon'; import { assert, expect } from 'chai'; -import * as sinon from 'sinon'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { DeployProgressBarFormatter } from '../../../src/formatters/deployProgressBarFormatter'; import { ProgressBar } from '../../../src/types'; describe('Progress Bar Events', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const username = 'me@my.org'; const deploy = new MetadataApiDeploy({ usernameOrConnection: username, id: '123' }); - const progressBarFormatter = new DeployProgressBarFormatter(new Logger('testing'), UX.prototype); + const progressBarFormatter = new DeployProgressBarFormatter(Ux.prototype); const initSpy = spyMethod(sandbox, progressBarFormatter, 'initProgressBar'); let bar: ProgressBar; let events: EventEmitter; @@ -29,12 +28,10 @@ describe('Progress Bar Events', () => { deploy.event = event; }; - const getProgressbar = () => + const getProgressbar = () => // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore protected member access - progressBarFormatter.progressBar - ; - + progressBarFormatter.progressBar; afterEach(() => { sandbox.restore(); }); diff --git a/test/commands/source/report.test.ts b/test/commands/source/report.test.ts index 6f1f8278a..15c53d4ec 100644 --- a/test/commands/source/report.test.ts +++ b/test/commands/source/report.test.ts @@ -6,14 +6,15 @@ */ import { join } from 'path'; -import * as fs from 'fs'; import * as sinon from 'sinon'; -import { assert, expect } from 'chai'; +import { expect } from 'chai'; import { fromStub, spyMethod, stubInterface, stubMethod } from '@salesforce/ts-sinon'; -import { ConfigFile, Org, SfProject } from '@salesforce/core'; +import { ConfigFile, SfProject } from '@salesforce/core'; import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; -import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; + +import { MetadataApiDeploy, MetadataApiDeployStatus } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; import { Report } from '../../../src/commands/force/source/deploy/report'; import { DeployReportResultFormatter } from '../../../src/formatters/deployReportResultFormatter'; import { DeployCommandResult } from '../../../src/formatters/deployResultFormatter'; @@ -23,8 +24,10 @@ import { Stash } from '../../../src/stash'; import { getDeployResult, getDeployResponse } from './deployResponses'; describe('force:source:report', () => { - const sandbox = sinon.createSandbox(); - const username = 'report-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'report-test@org.com'; const defaultDir = join('my', 'default', 'package'); const stashedDeployId = 'IMA000STASHID'; @@ -39,21 +42,16 @@ describe('force:source:report', () => { let checkDeployStatusStub: sinon.SinonStub; let uxLogStub: sinon.SinonStub; let pollStatusStub: sinon.SinonStub; - let readSyncStub: sinon.SinonStub; class TestReport extends Report { public async runIt() { - await this.init(); // oclif would normally populate this, but UT don't have it this.id ??= 'force:source:deploy:report'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:source:deploy:report'; + await this.init(); return this.run(); } - public setOrg(org: Org) { - this.org = org; - } - public setProject(project: SfProject) { - this.project = project; - } // eslint-disable-next-line class-methods-use-this public createDeploy(): MetadataApiDeploy { @@ -61,43 +59,31 @@ describe('force:source:report', () => { } } - const runReportCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 + const runReportCmd = async (params: string[], result?: MetadataApiDeployStatus) => { const cmd = new TestReport(params, oclifConfigStub); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getUniquePackageDirectories: () => [{ fullPath: defaultDir }], - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - getConnection: () => ({ - metadata: { - checkDeployStatus: checkDeployStatusStub, - }, - }), - }) - ); - cmd.setOrg(orgStub); - }); - uxLogStub = stubMethod(sandbox, UX.prototype, 'log'); + cmd.project = SfProject.getInstance(); + sandbox + .stub(cmd.project, 'getUniquePackageDirectories') + .returns([{ fullPath: defaultDir, path: defaultDir, name: '' }]); + + uxLogStub = stubMethod(sandbox, Ux.prototype, 'log'); stubMethod(sandbox, ConfigFile.prototype, 'get').returns({ jobid: stashedDeployId }); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + checkDeployStatusStub = sandbox.stub(cmd, 'report').resolves({ response: result ?? expectedResults }); return cmd.runIt(); }; - beforeEach(() => { - readSyncStub = stubMethod(sandbox, ConfigFile.prototype, 'readSync'); + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); + pollStatusStub = sandbox.stub(MetadataApiDeploy.prototype, 'pollStatus'); - checkDeployStatusStub = sandbox.stub().resolves(expectedResults); }); afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -106,45 +92,28 @@ describe('force:source:report', () => { const result = await runReportCmd(['--json']); expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(true); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(stashedDeployId); + expect(checkDeployStatusStub.firstCall.args[1]).to.equal(stashedDeployId); }); it('should display stashed deploy ID', async () => { const progressBarStub = sandbox.stub(DeployProgressBarFormatter.prototype, 'progress').returns(); const result = await runReportCmd([]); expect(result).to.deep.equal(expectedResults); - expect(uxLogStub.firstCall.args[0]).to.contain(stashedDeployId); expect(progressBarStub.calledOnce).to.equal(true); }); - it('should rename corrupt stash.json and throw an error', async () => { - const jsonParseError = new Error(); - jsonParseError.name = 'JsonParseError'; - readSyncStub.throws(jsonParseError); - const renameSyncStub = stubMethod(sandbox, fs, 'renameSync'); - try { - await runReportCmd(['--json']); - assert(false, 'Expected report command to throw a JsonParseError'); - } catch (error: unknown) { - const err = error as Error; - expect(err.name).to.equal('InvalidStashFile'); - expect(renameSyncStub.calledOnce).to.be.true; - } - }); - it('should use the jobid flag', async () => { const getStashSpy = spyMethod(sandbox, Stash, 'get'); const result = await runReportCmd(['--json', '--jobid', expectedResults.id]); expect(result).to.deep.equal(expectedResults); expect(getStashSpy.called).to.equal(false); - expect(checkDeployStatusStub.firstCall.args[0]).to.equal(expectedResults.id); + expect(checkDeployStatusStub.firstCall.args[1]).to.equal(expectedResults.id); }); it('should display the jobid flag', async () => { const progressBarStub = sandbox.stub(DeployProgressBarFormatter.prototype, 'progress').returns(); const result = await runReportCmd(['--jobid', expectedResults.id]); expect(result).to.deep.equal(expectedResults); - expect(uxLogStub.firstCall.args[0]).to.contain(expectedResults.id); expect(progressBarStub.calledOnce).to.equal(true); }); @@ -155,7 +124,7 @@ describe('force:source:report', () => { await runReportCmd([]); expect(displayStub.calledOnce).to.equal(true); expect(getJsonStub.calledOnce).to.equal(true); - expect(uxLogStub.called).to.equal(true); + expect(uxLogStub.called).to.equal(false); expect(progressBarStub.calledOnce).to.equal(true); }); @@ -183,7 +152,7 @@ describe('force:source:report', () => { pollStatusStub.throws(Error('The client has timed out')); checkDeployStatusStub.reset(); checkDeployStatusStub.resolves(inProgressDeployResult); - const result = await runReportCmd(['--json', '--wait', '1']); + const result = await runReportCmd(['--json', '--wait', '1'], inProgressDeployResult); expect(result).to.deep.equal(inProgressDeployResult); }); }); diff --git a/test/commands/source/retrieve.test.ts b/test/commands/source/retrieve.test.ts index 720debbd1..f8093f804 100644 --- a/test/commands/source/retrieve.test.ts +++ b/test/commands/source/retrieve.test.ts @@ -17,10 +17,11 @@ import { MetadataType, RetrieveOptions, } from '@salesforce/source-deploy-retrieve'; -import { Lifecycle, Messages, Org, SfProject } from '@salesforce/core'; +import { Lifecycle, Messages, SfProject } from '@salesforce/core'; import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon'; import { Config } from '@oclif/core'; -import { UX } from '@salesforce/command'; +import { SfCommand, Ux } from '@salesforce/sf-plugins-core'; +import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup'; import { Retrieve } from '../../../src/commands/force/source/retrieve'; import { RetrieveCommandResult, RetrieveResultFormatter } from '../../../src/formatters/retrieveResultFormatter'; import { getRetrieveResult } from './retrieveResponses'; @@ -30,8 +31,10 @@ Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/plugin-source', 'retrieve'); describe('force:source:retrieve', () => { - const sandbox = sinon.createSandbox(); - const username = 'retrieve-test@org.com'; + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + const sandbox = $$.SANDBOX; + testOrg.username = 'retrieve-test@org.com'; const packageXml = 'package.xml'; const defaultPackagePath = 'defaultPackagePath'; @@ -50,60 +53,41 @@ describe('force:source:retrieve', () => { let retrieveStub: sinon.SinonStub; let pollStub: sinon.SinonStub; let lifecycleEmitStub: sinon.SinonStub; - let resolveProjectConfigStub: sinon.SinonStub; let warnStub: sinon.SinonStub; class TestRetrieve extends Retrieve { public async runIt() { + // oclif would normally populate this, but UT don't have it + this.id ??= 'force:source:retrieve'; + // required for deprecation warnings to work correctly + this.ctor.id ??= 'force:source:retrieve'; await this.init(); return this.run(); } - - public setOrg(org: Org) { - this.org = org; - } - - public setProject(project: SfProject) { - this.project = project; - } } - const runRetrieveCmd = async (params: string[]) => { - // @ts-expect-error type mismatch between oclif/core v1 and v2 + const runRetrieveCmd = async (params: string[], options?: { sourceApiVersion?: string }) => { const cmd = new TestRetrieve(params, oclifConfigStub); - stubMethod(sandbox, SfProject, 'resolveProjectPath').resolves(join('path', 'to', 'package')); - stubMethod(sandbox, cmd, 'assignProject').callsFake(() => { - const SfProjectStub = fromStub( - stubInterface(sandbox, { - getDefaultPackage: () => ({ fullPath: defaultPackagePath }), - getUniquePackageDirectories: () => [{ fullPath: defaultPackagePath }], - getPackageDirectories: () => [{ fullPath: defaultPackagePath }], - resolveProjectConfig: resolveProjectConfigStub, - }) - ); - cmd.setProject(SfProjectStub); - }); - stubMethod(sandbox, cmd, 'assignOrg').callsFake(() => { - const orgStub = fromStub( - stubInterface(sandbox, { - getUsername: () => username, - }) - ); - cmd.setOrg(orgStub); - }); + cmd.project = SfProject.getInstance(); + sandbox.stub(cmd.project, 'getDefaultPackage').returns({ name: '', path: '', fullPath: defaultPackagePath }); + sandbox + .stub(cmd.project, 'getUniquePackageDirectories') + .returns([{ fullPath: defaultPackagePath, path: '', name: '' }]); + sandbox.stub(cmd.project, 'getPackageDirectories').returns([{ fullPath: defaultPackagePath, path: '', name: '' }]); + sandbox.stub(cmd.project, 'resolveProjectConfig').resolves({ sourceApiVersion: options?.sourceApiVersion }); + // keep the stdout from showing up in the test output - stubMethod(sandbox, UX.prototype, 'log'); - stubMethod(sandbox, UX.prototype, 'setSpinnerStatus'); - stubMethod(sandbox, UX.prototype, 'startSpinner'); - stubMethod(sandbox, UX.prototype, 'stopSpinner'); - stubMethod(sandbox, UX.prototype, 'styledHeader'); - stubMethod(sandbox, UX.prototype, 'table'); + stubMethod(sandbox, Ux.prototype, 'log'); + stubMethod(sandbox, Ux.prototype, 'styledHeader'); + stubMethod(sandbox, Ux.prototype, 'table'); stubMethod(sandbox, Retrieve.prototype, 'moveResultsForRetrieveTargetDir'); return cmd.runIt(); }; - beforeEach(() => { - resolveProjectConfigStub = sandbox.stub(); + beforeEach(async () => { + await $$.stubAuths(testOrg); + await $$.stubConfig({ 'target-org': testOrg.username }); + pollStub = sandbox.stub().resolves(retrieveResult); retrieveStub = sandbox.stub().resolves({ pollStatus: pollStub, @@ -116,10 +100,11 @@ describe('force:source:retrieve', () => { has: () => false, }); lifecycleEmitStub = sandbox.stub(Lifecycle.prototype, 'emit'); - warnStub = stubMethod(sandbox, UX.prototype, 'warn'); + warnStub = stubMethod(sandbox, SfCommand.prototype, 'warn'); }); afterEach(() => { + $$.restore(); sandbox.restore(); }); @@ -142,7 +127,7 @@ describe('force:source:retrieve', () => { // Ensure ComponentSet.retrieve() args const ensureRetrieveArgs = (overrides?: Partial) => { const defaultRetrieveArgs = { - usernameOrConnection: username, + usernameOrConnection: testOrg.username, merge: true, output: defaultPackagePath, packageOptions: undefined, @@ -233,9 +218,8 @@ describe('force:source:retrieve', () => { it('should pass along sourceapiversion', async () => { const sourceApiVersion = '50.0'; - resolveProjectConfigStub.resolves({ sourceApiVersion }); const manifest = 'package.xml'; - const result = await runRetrieveCmd(['--manifest', manifest, '--json']); + const result = await runRetrieveCmd(['--manifest', manifest, '--json'], { sourceApiVersion }); expect(result).to.deep.equal(expectedResults); ensureCreateComponentSetArgs({ sourceapiversion: sourceApiVersion, @@ -252,7 +236,10 @@ describe('force:source:retrieve', () => { const manifest = 'package.xml'; const packagenames = ['package1']; const result = await runRetrieveCmd(['--manifest', manifest, '--packagenames', packagenames[0], '--json']); - expectedResults.packages.push({ name: packagenames[0], path: join('path', 'to', 'package', packagenames[0]) }); + expectedResults.packages.push({ + name: packagenames[0], + path: join(await SfProject.resolveProjectPath(), packagenames[0]), + }); expect(result).to.deep.equal(expectedResults); ensureCreateComponentSetArgs({ packagenames, @@ -270,10 +257,19 @@ describe('force:source:retrieve', () => { it('should pass along multiple packagenames', async () => { const manifest = 'package.xml'; const packagenames = ['package1', 'package2']; - const result = await runRetrieveCmd(['--manifest', manifest, '--packagenames', packagenames.join(','), '--json']); - packagenames.forEach((pkg) => { - expectedResults.packages.push({ name: pkg, path: join('path', 'to', 'package', pkg) }); - }); + const result = await runRetrieveCmd([ + '--manifest', + manifest, + '--packagenames', + 'package1', + '--packagenames', + 'package2', + '--json', + ]); + for (const pkg of packagenames) { + // eslint-disable-next-line no-await-in-loop + expectedResults.packages.push({ name: pkg, path: join(await SfProject.resolveProjectPath(), pkg) }); + } expect(result).to.deep.equal(expectedResults); ensureCreateComponentSetArgs({ packagenames, @@ -332,7 +328,7 @@ describe('force:source:retrieve', () => { }); await runRetrieveCmd(['--metadata', metadata]); expect(warnStub.calledOnce); - expect(warnStub.firstCall.firstArg).to.equal(messages.getMessage('wantsToRetrieveCustomFields')); + expect(warnStub.secondCall.firstArg).to.equal(messages.getMessage('wantsToRetrieveCustomFields')); }); it('should not warn users when retrieving CustomField,CustomObject with --metadata', async () => { @@ -362,7 +358,7 @@ describe('force:source:retrieve', () => { }, }); await runRetrieveCmd(['--metadata', metadata]); - expect(warnStub.callCount).to.be.equal(0); + expect(warnStub.callCount).to.be.equal(1); }); it('should warn users when retrieving CustomField with --manifest', async () => { @@ -393,7 +389,7 @@ describe('force:source:retrieve', () => { }); await runRetrieveCmd(['--manifest', manifest]); expect(warnStub.calledOnce); - expect(warnStub.firstCall.firstArg).to.equal(messages.getMessage('wantsToRetrieveCustomFields')); + expect(warnStub.secondCall.firstArg).to.equal(messages.getMessage('wantsToRetrieveCustomFields')); }); it('should not be warn users when retrieving CustomField,CustomObject with --manifest', async () => { @@ -423,6 +419,6 @@ describe('force:source:retrieve', () => { }, }); await runRetrieveCmd(['--manifest', manifest]); - expect(warnStub.callCount).to.be.equal(0); + expect(warnStub.callCount).to.be.equal(1); }); }); diff --git a/test/commands/source/sourceCommand.test.ts b/test/commands/source/sourceCommand.test.ts deleted file mode 100644 index c728e67a0..000000000 --- a/test/commands/source/sourceCommand.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -/* eslint-disable class-methods-use-this */ - -import * as sinon from 'sinon'; -import { expect } from 'chai'; -import { stubInterface, fromStub } from '@salesforce/ts-sinon'; -import { Dictionary } from '@salesforce/ts-types'; -import { Logger } from '@salesforce/core'; -import { SourceCommand } from '../../../src/sourceCommand'; - -describe('SourceCommand', () => { - const sandbox = sinon.createSandbox(); - - afterEach(() => { - sandbox.restore(); - }); - - class SourceCommandTest extends SourceCommand { - protected logger = fromStub( - stubInterface(sandbox, { - debug: () => {}, - isDebugEnabled: () => false, - }) - ); - public async run() {} - public callSetExitCode(exitCode: number) { - this.setExitCode(exitCode); - } - public setCmdFlags(flags: Dictionary) { - this.flags = flags; - } - public callIsJsonOutput() { - return this.isJsonOutput(); - } - public resolveSuccess() {} - public formatResult() {} - } - - describe('isJsonOutput', () => { - it('should return true when json flag is set', () => { - const command = new SourceCommandTest([''], null); - command.setCmdFlags({ json: true }); - expect(command.callIsJsonOutput()).to.equal(true); - }); - - it('should return false when json flag is unset', () => { - const command = new SourceCommandTest([''], null); - expect(command.callIsJsonOutput()).to.equal(false); - }); - }); - - describe('setExitCode', () => { - const exitCode = process.exitCode; - it('should set process.exitCode', () => { - const testCode = 100; - const command = new SourceCommandTest([''], null); - command.callSetExitCode(testCode); - expect(process.exitCode).to.equal(testCode); - }); - - after(() => { - process.exitCode = exitCode; - }); - }); -}); diff --git a/test/commands/source/testConsts.ts b/test/commands/source/testConsts.ts index 90199cf59..17396a6ab 100644 --- a/test/commands/source/testConsts.ts +++ b/test/commands/source/testConsts.ts @@ -24,76 +24,6 @@ export const exampleSourceComponent: ComponentProperties = { content: '/dreamhouse-lwc/force-app/main/default/classes/GeocodingService.cls', }; -export const exampleDeployResponse = { - result: { - canceledBy: '0051h000006BHOq', - canceledByName: 'User User', - checkOnly: false, - completedDate: '2021-04-09T20:23:05.000Z', - createdBy: '0051h000006BHOq', - createdByName: 'User User', - createdDate: '2021-04-09T20:22:58.000Z', - details: { - componentSuccesses: [ - { - changed: 'false', - componentType: 'CustomField', - created: 'false', - createdDate: '2021-04-09T20:23:02.000Z', - deleted: 'false', - fileName: 'sdx_sourceDeploy_pkg_1617999776176/objects/Property__c.object', - fullName: 'Property__c.Picture__c', - id: '00N1h00000ApoBMEAZ', - success: 'true', - }, - { - changed: 'false', - componentType: 'CustomField', - created: 'false', - createdDate: '2021-04-09T20:23:02.000Z', - deleted: 'false', - fileName: 'sdx_sourceDeploy_pkg_1617999776176/objects/Property__c.object', - fullName: 'Property__c.Baths__c', - id: '00N1h00000ApoAuEAJ', - success: 'true', - }, - { - changed: 'false', - componentType: 'CustomField', - created: 'false', - createdDate: '2021-04-09T20:23:02.000Z', - deleted: 'false', - fileName: 'sdx_sourceDeploy_pkg_1617999776176/objects/Property__c.object', - fullName: 'Property__c.Price__c', - id: '00N1h00000ApoBOEAZ', - success: 'true', - }, - ], - runTestResult: { - numFailures: '0', - numTestsRun: '0', - totalTime: '0.0', - }, - }, - done: true, - id: '0Af1h00000fCQgsCAG', - ignoreWarnings: false, - lastModifiedDate: '2021-04-09T20:23:05.000Z', - numberComponentErrors: 0, - numberComponentsDeployed: 32, - numberComponentsTotal: 86, - numberTestErrors: 0, - numberTestsCompleted: 5, - numberTestsTotal: 10, - rollbackOnError: true, - runTestsEnabled: false, - startDate: '2021-04-09T20:22:58.000Z', - status: 'Canceled', - success: false, - }, - status: 0, -}; - export const exampleDeleteResponse = { // required but ignored by the delete UT getFileResponses: (): void => {}, diff --git a/test/formatters/deployProgressStatusFormatter.ts b/test/formatters/deployProgressStatusFormatter.ts index ee9a79fd8..0e94ff794 100644 --- a/test/formatters/deployProgressStatusFormatter.ts +++ b/test/formatters/deployProgressStatusFormatter.ts @@ -7,8 +7,7 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; +import { Ux } from '@salesforce/sf-plugins-core'; import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve'; import { getDeployResult } from '../commands/source/deployResponses'; import { DeployProgressStatusFormatter } from '../../src/formatters/deployProgressStatusFormatter'; @@ -16,7 +15,6 @@ import { DeployProgressStatusFormatter } from '../../src/formatters/deployProgre describe('DeployProgressStatusFormatter', () => { const sandbox = sinon.createSandbox(); const deployResultInProgress = getDeployResult('inProgress'); - const logger = Logger.childFromRoot('deployTestLogger').useMemoryLogging(); let ux; let printStub: sinon.SinonStub; let mdApiDeploy: MetadataApiDeploy; @@ -40,7 +38,7 @@ describe('DeployProgressStatusFormatter', () => { }; it('should output with every update when verbose', async () => { - const formatter = new DeployProgressStatusFormatter(logger, ux as UX, { verbose: true }); + const formatter = new DeployProgressStatusFormatter(ux as Ux, { verbose: true }); formatter.progress(mdApiDeploy); fireUpdateEvent(); @@ -54,7 +52,7 @@ describe('DeployProgressStatusFormatter', () => { }); it('should only output on update when results change without verbose', async () => { - const formatter = new DeployProgressStatusFormatter(logger, ux as UX); + const formatter = new DeployProgressStatusFormatter(ux as Ux); formatter.progress(mdApiDeploy); fireUpdateEvent(); diff --git a/test/formatters/deployResultFormatter.test.ts b/test/formatters/deployResultFormatter.test.ts index 07c5a9b81..ccb3747f6 100644 --- a/test/formatters/deployResultFormatter.test.ts +++ b/test/formatters/deployResultFormatter.test.ts @@ -8,15 +8,15 @@ import * as path from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { DeployResult, FileResponse } from '@salesforce/source-deploy-retrieve'; import { stubInterface } from '@salesforce/ts-sinon'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { getDeployResult } from '../commands/source/deployResponses'; import { DeployCommandResult, DeployResultFormatter } from '../../src/formatters/deployResultFormatter'; describe('DeployResultFormatter', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const deployResultSuccess = getDeployResult('successSync'); const deployResultFailure = getDeployResult('failed'); @@ -25,7 +25,6 @@ describe('DeployResultFormatter', () => { const deployResultTestSuccess = getDeployResult('passedTest'); const deployResultTestSuccessAndFailure = getDeployResult('passedAndFailedTest'); - const logger = Logger.childFromRoot('deployTestLogger').useMemoryLogging(); let ux; let logStub: sinon.SinonStub; @@ -44,7 +43,7 @@ describe('DeployResultFormatter', () => { logStub = sandbox.stub(); styledHeaderStub = sandbox.stub(); tableStub = sandbox.stub(); - ux = stubInterface(sandbox, { + ux = stubInterface(sandbox, { log: logStub, styledHeader: styledHeaderStub, table: tableStub, @@ -60,7 +59,7 @@ describe('DeployResultFormatter', () => { it('should return expected json for a success', async () => { const deployResponse = JSON.parse(JSON.stringify(deployResultSuccess.response)) as DeployCommandResult; const expectedSuccessResults = deployResultSuccess.response as DeployCommandResult; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployResultSuccess); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployResultSuccess); const json = formatter.getJson(); expectedSuccessResults.deployedSource = deployResultSuccess.getFileResponses(); @@ -75,7 +74,7 @@ describe('DeployResultFormatter', () => { expectedFailureResults.deployedSource = deployResultFailure.getFileResponses(); expectedFailureResults.outboundFiles = []; expectedFailureResults.deploys = [deployResponse]; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployResultFailure); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployResultFailure); expect(formatter.getJson()).to.deep.equal(expectedFailureResults); }); @@ -85,7 +84,7 @@ describe('DeployResultFormatter', () => { expectedPartialSuccessResponse.deployedSource = deployResultPartialSuccess.getFileResponses(); expectedPartialSuccessResponse.outboundFiles = []; expectedPartialSuccessResponse.deploys = [deployResponse]; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployResultPartialSuccess); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployResultPartialSuccess); expect(formatter.getJson()).to.deep.equal(expectedPartialSuccessResponse); }); @@ -95,7 +94,7 @@ describe('DeployResultFormatter', () => { ...(JSON.parse(JSON.stringify(deployResultSuccess)) as DeployResult), replacements: new Map([['MyApexClass.cls', ['foo', 'bar']]]), }; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, resultWithReplacements as DeployResult); + const formatter = new DeployResultFormatter(ux as Ux, {}, resultWithReplacements as DeployResult); const json = formatter.getJson(); expect(json.replacements).to.deep.equal({ 'MyApexClass.cls': ['foo', 'bar'] }); @@ -104,7 +103,7 @@ describe('DeployResultFormatter', () => { const resultWithoutReplacements = { ...(JSON.parse(JSON.stringify(deployResultSuccess)) as DeployResult), }; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, resultWithoutReplacements as DeployResult); + const formatter = new DeployResultFormatter(ux as Ux, {}, resultWithoutReplacements as DeployResult); const json = formatter.getJson(); expect(json.replacements).to.be.undefined; }); @@ -113,7 +112,7 @@ describe('DeployResultFormatter', () => { ...(JSON.parse(JSON.stringify(deployResultSuccess)) as DeployResult), replacements: new Map(), }; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, resultWithEmptyReplacements as DeployResult); + const formatter = new DeployResultFormatter(ux as Ux, {}, resultWithEmptyReplacements as DeployResult); const json = formatter.getJson(); expect(json.replacements).to.be.undefined; }); @@ -122,7 +121,7 @@ describe('DeployResultFormatter', () => { describe('display', () => { it('should output as expected for a success', async () => { - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployResultSuccess); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployResultSuccess); formatter.display(); expect(styledHeaderStub.calledOnce).to.equal(true); expect(logStub.callCount).to.equal(2); @@ -134,7 +133,7 @@ describe('DeployResultFormatter', () => { }); it('should output as expected for a failure and exclude duplicate information', async () => { - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployResultFailure); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployResultFailure); formatter.display(); expect(styledHeaderStub.calledOnce).to.equal(true); expect(logStub.callCount).to.equal(3); @@ -152,7 +151,7 @@ describe('DeployResultFormatter', () => { deployFailure.response.details.componentFailures = []; deployFailure.response.details.componentSuccesses = []; delete deployFailure.response.details.runTestResult; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, deployFailure); + const formatter = new DeployResultFormatter(ux as Ux, {}, deployFailure); sandbox.stub(formatter, 'isSuccess').returns(false); try { @@ -167,7 +166,7 @@ describe('DeployResultFormatter', () => { }); it('should output as expected for a test failure with verbose', async () => { - const formatter = new DeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultTestFailure); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestFailure); formatter.display(); expect(styledHeaderStub.calledThrice).to.equal(true); expect(logStub.callCount).to.equal(8); @@ -178,7 +177,7 @@ describe('DeployResultFormatter', () => { }); it('should output as expected for passing tests with verbose', async () => { - const formatter = new DeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultTestSuccess); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestSuccess); formatter.display(); expect(styledHeaderStub.calledThrice).to.equal(true); expect(logStub.callCount).to.equal(8); @@ -189,12 +188,7 @@ describe('DeployResultFormatter', () => { }); it('should output as expected for passing and failing tests with verbose', async () => { - const formatter = new DeployResultFormatter( - logger, - ux as UX, - { verbose: true }, - deployResultTestSuccessAndFailure - ); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestSuccessAndFailure); formatter.display(); expect(styledHeaderStub.callCount).to.equal(4); expect(logStub.callCount).to.equal(9); @@ -206,7 +200,7 @@ describe('DeployResultFormatter', () => { }); it('shows success AND failures for partialSucceeded', async () => { - const formatter = new DeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultPartialSuccess); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, deployResultPartialSuccess); formatter.display(); expect(styledHeaderStub.callCount, 'styledHeaderStub.callCount').to.equal(2); expect(logStub.callCount, 'logStub.callCount').to.equal(4); @@ -221,7 +215,7 @@ describe('DeployResultFormatter', () => { const resultWithoutReplacements = { ...deployResultSuccess, } as DeployResult; - const formatter = new DeployResultFormatter(logger, ux as UX, { verbose: true }, resultWithoutReplacements); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, resultWithoutReplacements); formatter.display(); @@ -236,7 +230,7 @@ describe('DeployResultFormatter', () => { ...deployResultSuccess, replacements: new Map([['MyApexClass.cls', ['foo', 'bar']]]), } as DeployResult; - const formatter = new DeployResultFormatter(logger, ux as UX, { verbose: true }, resultWithReplacements); + const formatter = new DeployResultFormatter(ux as Ux, { verbose: true }, resultWithReplacements); formatter.display(); expect(logStub.callCount, 'logStub.callCount').to.equal(3); @@ -251,7 +245,7 @@ describe('DeployResultFormatter', () => { ...deployResultSuccess, replacements: new Map([['MyApexClass.cls', ['foo', 'bar']]]), } as DeployResult; - const formatter = new DeployResultFormatter(logger, ux as UX, {}, resultWithReplacements); + const formatter = new DeployResultFormatter(ux as Ux, {}, resultWithReplacements); formatter.display(); expect(logStub.callCount, 'logStub.callCount').to.equal(2); diff --git a/test/formatters/mdDeployResultFormatter.test.ts b/test/formatters/mdDeployResultFormatter.test.ts index 5113c87de..8f883f7f1 100644 --- a/test/formatters/mdDeployResultFormatter.test.ts +++ b/test/formatters/mdDeployResultFormatter.test.ts @@ -4,17 +4,16 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ - import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { stubInterface } from '@salesforce/ts-sinon'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { getDeployResult } from '../commands/source/deployResponses'; import { MdDeployResultFormatter } from '../../src/formatters/mdapi/mdDeployResultFormatter'; describe('mdDeployResultFormatter', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const deployResultSuccess = getDeployResult('successSync'); const deployResultFailure = getDeployResult('failed'); @@ -23,7 +22,6 @@ describe('mdDeployResultFormatter', () => { const deployResultTestSuccess = getDeployResult('passedTest'); const deployResultTestSuccessAndFailure = getDeployResult('passedAndFailedTest'); - const logger = Logger.childFromRoot('deployTestLogger').useMemoryLogging(); let ux; let logStub: sinon.SinonStub; @@ -34,7 +32,7 @@ describe('mdDeployResultFormatter', () => { logStub = sandbox.stub(); styledHeaderStub = sandbox.stub(); tableStub = sandbox.stub(); - ux = stubInterface(sandbox, { + ux = stubInterface(sandbox, { log: logStub, styledHeader: styledHeaderStub, table: tableStub, @@ -51,7 +49,7 @@ describe('mdDeployResultFormatter', () => { it('should return expected json for a success', async () => { process.exitCode = 0; const expectedSuccessResults = deployResultSuccess.response; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployResultSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployResultSuccess); const json = formatter.getJson(); expect(json).to.deep.equal(expectedSuccessResults); @@ -61,14 +59,14 @@ describe('mdDeployResultFormatter', () => { process.exitCode = 1; const expectedFailureResults = deployResultFailure.response; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployResultFailure); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployResultFailure); expect(formatter.getJson()).to.deep.equal(expectedFailureResults); }); it('should return expected json for a partial success', () => { process.exitCode = 69; const expectedPartialSuccessResponse = deployResultPartialSuccess.response; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployResultPartialSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployResultPartialSuccess); expect(formatter.getJson()).to.deep.equal(expectedPartialSuccessResponse); }); @@ -76,7 +74,7 @@ describe('mdDeployResultFormatter', () => { process.exitCode = 0; const expectedSuccessResults = deployResultSuccess.response; - const formatter = new MdDeployResultFormatter(logger, ux as UX, { concise: true }, deployResultSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, { concise: true }, deployResultSuccess); const json = formatter.getJson(); // a few checks that it's the rest of the json @@ -90,7 +88,7 @@ describe('mdDeployResultFormatter', () => { describe('display', () => { it('should output as expected for a success (no table)', async () => { process.exitCode = 0; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployResultSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployResultSuccess); formatter.display(); expect(logStub.callCount).to.equal(0); expect(tableStub.callCount).to.equal(0); @@ -99,7 +97,7 @@ describe('mdDeployResultFormatter', () => { it('should output as expected for a verbose success (has table)', async () => { process.exitCode = 0; - const formatter = new MdDeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, { verbose: true }, deployResultSuccess); formatter.display(); expect(styledHeaderStub.callCount).to.equal(1); expect(logStub.callCount).to.equal(1); @@ -110,7 +108,7 @@ describe('mdDeployResultFormatter', () => { it('should output as expected for a failure and exclude duplicate information', async () => { process.exitCode = 1; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployResultFailure); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployResultFailure); try { formatter.display(); @@ -130,7 +128,7 @@ describe('mdDeployResultFormatter', () => { deployFailure.response.details.componentFailures = []; deployFailure.response.details.componentSuccesses = []; delete deployFailure.response.details.runTestResult; - const formatter = new MdDeployResultFormatter(logger, ux as UX, {}, deployFailure); + const formatter = new MdDeployResultFormatter(ux as Ux, {}, deployFailure); sandbox.stub(formatter, 'isSuccess').returns(false); try { @@ -146,7 +144,7 @@ describe('mdDeployResultFormatter', () => { it('should output as expected for a test failure with verbose', async () => { process.exitCode = 1; - const formatter = new MdDeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultTestFailure); + const formatter = new MdDeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestFailure); try { formatter.display(); throw new Error('should have thrown'); @@ -163,7 +161,7 @@ describe('mdDeployResultFormatter', () => { it('should output as expected for passing tests with verbose', async () => { process.exitCode = 0; - const formatter = new MdDeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultTestSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestSuccess); formatter.display(); expect(styledHeaderStub.args[0][0]).to.include('Deployed Source'); expect(styledHeaderStub.args[1][0]).to.include('Component Failures [1]'); @@ -173,12 +171,7 @@ describe('mdDeployResultFormatter', () => { it('should output as expected for passing and failing tests with verbose', async () => { process.exitCode = 1; - const formatter = new MdDeployResultFormatter( - logger, - ux as UX, - { verbose: true }, - deployResultTestSuccessAndFailure - ); + const formatter = new MdDeployResultFormatter(ux as Ux, { verbose: true }, deployResultTestSuccessAndFailure); try { formatter.display(); throw new Error('should have thrown'); @@ -195,7 +188,7 @@ describe('mdDeployResultFormatter', () => { it('shows success AND failures for partialSucceeded', async () => { process.exitCode = 69; - const formatter = new MdDeployResultFormatter(logger, ux as UX, { verbose: true }, deployResultPartialSuccess); + const formatter = new MdDeployResultFormatter(ux as Ux, { verbose: true }, deployResultPartialSuccess); formatter.display(); expect(styledHeaderStub.callCount, 'styledHeaderStub.callCount').to.equal(2); expect(logStub.callCount, 'logStub.callCount').to.equal(3); diff --git a/test/formatters/pullFormatter.test.ts b/test/formatters/pullFormatter.test.ts index 4146b507a..0bafb2e39 100644 --- a/test/formatters/pullFormatter.test.ts +++ b/test/formatters/pullFormatter.test.ts @@ -8,16 +8,16 @@ import { relative } from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { FileResponse } from '@salesforce/source-deploy-retrieve'; import { stubInterface } from '@salesforce/ts-sinon'; import { ensureArray } from '@salesforce/kit'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { getRetrieveResult } from '../commands/source/retrieveResponses'; import { PullResponse, PullResultFormatter } from '../../src/formatters/source/pullFormatter'; describe('PullFormatter', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const retrieveResultSuccess = getRetrieveResult('success'); const retrieveResultFailure = getRetrieveResult('failed'); @@ -25,7 +25,6 @@ describe('PullFormatter', () => { const retrieveResultEmpty = getRetrieveResult('empty'); const retrieveResultWarnings = getRetrieveResult('warnings'); - const logger = Logger.childFromRoot('retrieveTestLogger').useMemoryLogging(); let ux; let logStub: sinon.SinonStub; let styledHeaderStub: sinon.SinonStub; @@ -43,7 +42,7 @@ describe('PullFormatter', () => { logStub = sandbox.stub(); styledHeaderStub = sandbox.stub(); tableStub = sandbox.stub(); - ux = stubInterface(sandbox, { + ux = stubInterface(sandbox, { log: logStub, styledHeader: styledHeaderStub, table: tableStub, @@ -59,14 +58,14 @@ describe('PullFormatter', () => { it('should return expected json for a success', async () => { process.exitCode = 0; const expectedSuccessResults: PullResponse['pulledSource'] = retrieveResultSuccess.getFileResponses(); - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultSuccess); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultSuccess); expect(formatter.getJson().pulledSource).to.deep.equal(expectedSuccessResults); }); it('should return expected json for a failure', async () => { process.exitCode = 1; const expectedFailureResults: PullResponse['pulledSource'] = retrieveResultFailure.getFileResponses(); - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultFailure); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultFailure); try { formatter.getJson().pulledSource; throw new Error('should have thrown'); @@ -80,14 +79,14 @@ describe('PullFormatter', () => { it('should return expected json for an InProgress', async () => { const expectedInProgressResults: PullResponse['pulledSource'] = retrieveResultInProgress.getFileResponses(); - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultInProgress); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultInProgress); expect(formatter.getJson().pulledSource).to.deep.equal(expectedInProgressResults); }); describe('display', () => { it('should output as expected for a success', async () => { process.exitCode = 0; - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultSuccess); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultSuccess); formatter.display(); expect(styledHeaderStub.called).to.equal(true); expect(logStub.called).to.equal(false); @@ -101,7 +100,7 @@ describe('PullFormatter', () => { it('should output as expected for an InProgress', async () => { process.exitCode = 68; const options = { waitTime: 33 }; - const formatter = new PullResultFormatter(logger, ux as UX, options, retrieveResultInProgress); + const formatter = new PullResultFormatter(ux as Ux, options, retrieveResultInProgress); formatter.display(); expect(styledHeaderStub.called).to.equal(false); expect(logStub.called).to.equal(true); @@ -113,7 +112,7 @@ describe('PullFormatter', () => { it('should output as expected for a Failure', async () => { process.exitCode = 1; - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultFailure); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultFailure); sandbox.stub(formatter, 'isSuccess').returns(false); formatter.display(); @@ -124,7 +123,7 @@ describe('PullFormatter', () => { it('should output as expected for warnings', async () => { process.exitCode = 0; - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultWarnings); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultWarnings); formatter.display(); // Should call styledHeader for warnings and the standard "Retrieved Source" header expect(styledHeaderStub.calledTwice).to.equal(true); @@ -138,7 +137,7 @@ describe('PullFormatter', () => { it('should output a message when no results were returned', async () => { process.exitCode = 0; - const formatter = new PullResultFormatter(logger, ux as UX, {}, retrieveResultEmpty); + const formatter = new PullResultFormatter(ux as Ux, {}, retrieveResultEmpty); formatter.display(); expect(styledHeaderStub.called).to.equal(true); expect(logStub.called).to.equal(true); diff --git a/test/formatters/pushResultFormatter.test.ts b/test/formatters/pushResultFormatter.test.ts index 212f0a764..e348ca70a 100644 --- a/test/formatters/pushResultFormatter.test.ts +++ b/test/formatters/pushResultFormatter.test.ts @@ -5,23 +5,22 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import * as sinon from 'sinon'; import { stubInterface } from '@salesforce/ts-sinon'; import { DeployResult } from '@salesforce/source-deploy-retrieve'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { getDeployResult } from '../commands/source/deployResponses'; import { PushResultFormatter, mergeReplacements } from '../../src/formatters/source/pushResultFormatter'; describe('PushResultFormatter', () => { - const logger = Logger.childFromRoot('deployTestLogger').useMemoryLogging(); const deployResultSuccess = [getDeployResult('successSync')]; const deployResultSuccessWithReplacements = [ { ...getDeployResult('successSync'), replacements: new Map([['foo', ['bar', 'baz']]]) }, ] as DeployResult[]; const deployResultFailure = [getDeployResult('failed')]; - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; let uxMock; let tableStub: sinon.SinonStub; @@ -29,7 +28,7 @@ describe('PushResultFormatter', () => { beforeEach(() => { tableStub = sandbox.stub(); headerStub = sandbox.stub(); - uxMock = stubInterface(sandbox, { + uxMock = stubInterface(sandbox, { table: tableStub, styledHeader: headerStub, }); @@ -53,7 +52,7 @@ describe('PushResultFormatter', () => { }; it('returns expected json for success', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, new UX(logger), {}, deployResultSuccess); + const formatter = new PushResultFormatter(uxMock as Ux, {}, deployResultSuccess); expect(formatter.getJson().pushedSource).to.deep.equal([ { filePath: 'classes/ProductController.cls', @@ -65,7 +64,7 @@ describe('PushResultFormatter', () => { }); it('returns expected json for success with replaements', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, new UX(logger), {}, deployResultSuccessWithReplacements); + const formatter = new PushResultFormatter(uxMock as Ux, {}, deployResultSuccessWithReplacements); const result = formatter.getJson(); expect(result.pushedSource).to.deep.equal([ { @@ -80,7 +79,7 @@ describe('PushResultFormatter', () => { }); }); it('returns expected json for failure', () => { - const formatter = new PushResultFormatter(logger, new UX(logger), {}, deployResultFailure); + const formatter = new PushResultFormatter(uxMock as Ux, {}, deployResultFailure); process.exitCode = 1; try { @@ -98,23 +97,18 @@ describe('PushResultFormatter', () => { describe('json with quiet', () => { it('honors quiet flag for json successes', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, new UX(logger), { quiet: true }, deployResultSuccess); + const formatter = new PushResultFormatter(uxMock as Ux, { quiet: true }, deployResultSuccess); expect(formatter.getJson().pushedSource).to.deep.equal([]); expect(formatter.getJson().replacements).to.be.undefined; }); it('omits replacements', () => { process.exitCode = 0; - const formatter = new PushResultFormatter( - logger, - new UX(logger), - { quiet: true }, - deployResultSuccessWithReplacements - ); + const formatter = new PushResultFormatter(uxMock as Ux, { quiet: true }, deployResultSuccessWithReplacements); expect(formatter.getJson().pushedSource).to.deep.equal([]); expect(formatter.getJson().replacements).to.be.undefined; }); it('honors quiet flag for json failure', () => { - const formatter = new PushResultFormatter(logger, new UX(logger), { quiet: true }, deployResultFailure); + const formatter = new PushResultFormatter(uxMock as Ux, { quiet: true }, deployResultFailure); try { formatter.getJson(); throw new Error('should have thrown'); @@ -129,14 +123,14 @@ describe('PushResultFormatter', () => { describe('human output', () => { it('returns expected output for success', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, uxMock as UX, {}, deployResultSuccess); + const formatter = new PushResultFormatter(uxMock as Ux, {}, deployResultSuccess); formatter.display(); expect(headerStub.callCount, JSON.stringify(headerStub.args)).to.equal(1); expect(tableStub.callCount, JSON.stringify(tableStub.args)).to.equal(1); }); it('returns expected output for success with replacements', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, uxMock as UX, {}, deployResultSuccessWithReplacements); + const formatter = new PushResultFormatter(uxMock as Ux, {}, deployResultSuccessWithReplacements); formatter.display(); expect(headerStub.callCount, JSON.stringify(headerStub.args)).to.equal(2); expect(headerStub.args[0][0]).to.include('Pushed Source'); @@ -150,7 +144,7 @@ describe('PushResultFormatter', () => { deployFailure.response.details.componentFailures = []; deployFailure.response.details.componentSuccesses = []; delete deployFailure.response.details.runTestResult; - const formatter = new PushResultFormatter(logger, uxMock as UX, {}, [deployFailure]); + const formatter = new PushResultFormatter(uxMock as Ux, {}, [deployFailure]); sandbox.stub(formatter, 'isSuccess').returns(false); try { @@ -166,7 +160,7 @@ describe('PushResultFormatter', () => { describe('quiet', () => { it('does not display successes for quiet', () => { process.exitCode = 0; - const formatter = new PushResultFormatter(logger, uxMock as UX, { quiet: true }, deployResultSuccess); + const formatter = new PushResultFormatter(uxMock as Ux, { quiet: true }, deployResultSuccess); formatter.display(); expect(headerStub.callCount, JSON.stringify(headerStub.args)).to.equal(0); expect(formatter.getJson().pushedSource).to.deep.equal([]); @@ -174,7 +168,7 @@ describe('PushResultFormatter', () => { }); it('displays errors and throws for quiet', () => { process.exitCode = 1; - const formatter = new PushResultFormatter(logger, uxMock as UX, { quiet: true }, deployResultFailure); + const formatter = new PushResultFormatter(uxMock as Ux, { quiet: true }, deployResultFailure); try { formatter.display(); throw new Error('should have thrown'); diff --git a/test/formatters/retrieveResultFormatter.test.ts b/test/formatters/retrieveResultFormatter.test.ts index 24d662755..1cc111e83 100644 --- a/test/formatters/retrieveResultFormatter.test.ts +++ b/test/formatters/retrieveResultFormatter.test.ts @@ -8,16 +8,16 @@ import { join, relative } from 'path'; import * as sinon from 'sinon'; import { expect } from 'chai'; -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { FileResponse } from '@salesforce/source-deploy-retrieve'; import { cloneJson, ensureArray } from '@salesforce/kit'; import { stubInterface } from '@salesforce/ts-sinon'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { getRetrieveResult } from '../commands/source/retrieveResponses'; import { RetrieveCommandResult, RetrieveResultFormatter } from '../../src/formatters/retrieveResultFormatter'; describe('RetrieveResultFormatter', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const retrieveResultSuccess = getRetrieveResult('success'); const retrieveResultFailure = getRetrieveResult('failed'); @@ -25,7 +25,6 @@ describe('RetrieveResultFormatter', () => { const retrieveResultEmpty = getRetrieveResult('empty'); const retrieveResultWarnings = getRetrieveResult('warnings'); - const logger = Logger.childFromRoot('retrieveTestLogger').useMemoryLogging(); let ux; let logStub: sinon.SinonStub; let styledHeaderStub: sinon.SinonStub; @@ -43,7 +42,7 @@ describe('RetrieveResultFormatter', () => { logStub = sandbox.stub(); styledHeaderStub = sandbox.stub(); tableStub = sandbox.stub(); - ux = stubInterface(sandbox, { + ux = stubInterface(sandbox, { log: logStub, styledHeader: styledHeaderStub, table: tableStub, @@ -62,7 +61,7 @@ describe('RetrieveResultFormatter', () => { warnings: [], response: cloneJson(retrieveResultSuccess.response), }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultSuccess); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultSuccess); expect(formatter.getJson()).to.deep.equal(expectedSuccessResults); }); @@ -73,7 +72,7 @@ describe('RetrieveResultFormatter', () => { warnings: [], response: cloneJson(retrieveResultFailure.response), }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultFailure); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultFailure); expect(formatter.getJson()).to.deep.equal(expectedFailureResults); }); @@ -84,7 +83,7 @@ describe('RetrieveResultFormatter', () => { warnings: [], response: cloneJson(retrieveResultInProgress.response), }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultInProgress); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultInProgress); expect(formatter.getJson()).to.deep.equal(expectedInProgressResults); }); @@ -96,7 +95,7 @@ describe('RetrieveResultFormatter', () => { warnings: [], response: cloneJson(retrieveResultSuccess.response), }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, { packages: [testPkg] }, retrieveResultSuccess); + const formatter = new RetrieveResultFormatter(ux as Ux, { packages: [testPkg] }, retrieveResultSuccess); expect(formatter.getJson()).to.deep.equal(expectedSuccessResults); }); @@ -109,14 +108,14 @@ describe('RetrieveResultFormatter', () => { warnings, response: cloneJson(retrieveResultWarnings.response), }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultWarnings); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultWarnings); expect(formatter.getJson()).to.deep.equal(expectedSuccessResults); }); }); describe('display', () => { it('should output as expected for a success', async () => { - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultSuccess); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultSuccess); formatter.display(); expect(styledHeaderStub.called).to.equal(true); expect(logStub.called).to.equal(false); @@ -129,7 +128,7 @@ describe('RetrieveResultFormatter', () => { it('should output as expected for an InProgress', async () => { const options = { waitTime: 33 }; - const formatter = new RetrieveResultFormatter(logger, ux as UX, options, retrieveResultInProgress); + const formatter = new RetrieveResultFormatter(ux as Ux, options, retrieveResultInProgress); formatter.display(); expect(styledHeaderStub.called).to.equal(false); expect(logStub.called).to.equal(true); @@ -140,7 +139,7 @@ describe('RetrieveResultFormatter', () => { }); it('should output as expected for a Failure', async () => { - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultFailure); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultFailure); sandbox.stub(formatter, 'isSuccess').returns(false); formatter.display(); @@ -150,7 +149,7 @@ describe('RetrieveResultFormatter', () => { }); it('should output as expected for warnings', async () => { - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultWarnings); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultWarnings); formatter.display(); // Should call styledHeader for warnings and the standard "Retrieved Source" header expect(styledHeaderStub.calledTwice).to.equal(true); @@ -163,7 +162,7 @@ describe('RetrieveResultFormatter', () => { }); it('should output a message when no results were returned', async () => { - const formatter = new RetrieveResultFormatter(logger, ux as UX, {}, retrieveResultEmpty); + const formatter = new RetrieveResultFormatter(ux as Ux, {}, retrieveResultEmpty); formatter.display(); expect(styledHeaderStub.called).to.equal(true); expect(logStub.called).to.equal(true); diff --git a/test/formatters/statusResultFormatter.test.ts b/test/formatters/statusResultFormatter.test.ts index 9e5bea6b9..8275e91e3 100644 --- a/test/formatters/statusResultFormatter.test.ts +++ b/test/formatters/statusResultFormatter.test.ts @@ -4,11 +4,11 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { Logger } from '@salesforce/core'; -import { UX } from '@salesforce/command'; import { stubInterface } from '@salesforce/ts-sinon'; import { expect } from 'chai'; import * as sinon from 'sinon'; +import { Ux } from '@salesforce/sf-plugins-core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { StatusFormatter, StatusResult } from '../../src/formatters/source/statusFormatter'; const fakeResult: StatusResult[] = [ @@ -39,9 +39,8 @@ const fakeResult: StatusResult[] = [ ]; describe('status results', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; let ux; - const logger = Logger.childFromRoot('retrieveTestLogger').useMemoryLogging(); let logStub: sinon.SinonStub; let tableStub: sinon.SinonStub; @@ -49,7 +48,7 @@ describe('status results', () => { logStub = sandbox.stub(); tableStub = sandbox.stub(); - ux = stubInterface(sandbox, { + ux = stubInterface(sandbox, { log: logStub, table: tableStub, }); @@ -60,32 +59,32 @@ describe('status results', () => { }); it('returns expected json', () => { - const formatter = new StatusFormatter(logger, ux as UX, {}, fakeResult); + const formatter = new StatusFormatter(ux as Ux, {}, fakeResult); expect(formatter.getJson()).deep.equal(fakeResult); }); describe('human display', () => { it('includes ignored files without the concise option', () => { - const formatter = new StatusFormatter(logger, ux as UX, { concise: false }, fakeResult); + const formatter = new StatusFormatter(ux as Ux, { concise: false }, fakeResult); formatter.display(); expect(tableStub.callCount).to.equal(1); expect(tableStub.firstCall.args[0]).to.have.equal(fakeResult); }); it('omits ignored files with the concise option', () => { - const formatter = new StatusFormatter(logger, ux as UX, { concise: true }, fakeResult); + const formatter = new StatusFormatter(ux as Ux, { concise: true }, fakeResult); formatter.display(); expect(tableStub.callCount).to.equal(1); expect(tableStub.firstCall.args[0]).to.deep.equal([fakeResult[2]]); }); it('shows no results when there are none', () => { - const formatter = new StatusFormatter(logger, ux as UX, { concise: false }, []); + const formatter = new StatusFormatter(ux as Ux, { concise: false }, []); formatter.display(); expect(logStub.callCount).to.equal(1); expect(logStub.firstCall.args[0]).to.contain('No local or remote changes found.'); }); it('shows no results when there are none because concise omitted them', () => { - const formatter = new StatusFormatter(logger, ux as UX, { concise: true }, [fakeResult[0]]); + const formatter = new StatusFormatter(ux as Ux, { concise: true }, [fakeResult[0]]); formatter.display(); expect(logStub.callCount).to.equal(1); expect(logStub.firstCall.args[0]).to.contain('No local or remote changes found.'); diff --git a/test/hooks/diagnostics.test.ts b/test/hooks/diagnostics.test.ts index 804e8d45d..d82a5a60a 100644 --- a/test/hooks/diagnostics.test.ts +++ b/test/hooks/diagnostics.test.ts @@ -10,6 +10,7 @@ import { expect } from 'chai'; import { fromStub, StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon'; import { SfDoctor } from '@salesforce/plugin-info'; import { ConfigAggregator, Lifecycle, Messages, Org, SfProject } from '@salesforce/core'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { hook } from '../../src/hooks/diagnostics'; const pluginName = '@salesforce/plugin-source'; @@ -23,7 +24,7 @@ const messages = Messages.load(pluginName, 'diagnostics', [ ]); describe('Doctor diagnostics', () => { - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; // Stubs for: // 1. the Doctor class needed by the hook diff --git a/test/nuts/REST/deploy.mpd.nut.ts b/test/nuts/REST/deploy.mpd.nut.ts index 743c7ff70..c159a0760 100644 --- a/test/nuts/REST/deploy.mpd.nut.ts +++ b/test/nuts/REST/deploy.mpd.nut.ts @@ -114,8 +114,8 @@ context(`MPD REST Deploy NUTs [name: ${repo.name}]`, () => { }); } }); - - describe('--manifest flag', () => { + // skipping while convert is moved to PDR + describe.skip('--manifest flag', () => { for (const manifest of repo.deploy.manifest) { const toDeploy = path.normalize(manifest.toDeploy); it(`should deploy ${toDeploy}`, async () => { diff --git a/test/nuts/REST/deploy.nut.ts b/test/nuts/REST/deploy.nut.ts index a36d6d549..65f3d38ed 100644 --- a/test/nuts/REST/deploy.nut.ts +++ b/test/nuts/REST/deploy.nut.ts @@ -89,8 +89,8 @@ context(`REST Deploy NUTs [name: ${repo.name}]`, () => { }); } }); - - describe('--manifest', () => { + // skipping while convert is in PDR but unpublished + describe.skip('--manifest', () => { for (const testCase of repo.deploy.manifest) { const toDeploy = path.normalize(testCase.toDeploy); it(`should deploy ${toDeploy}`, async () => { diff --git a/test/nuts/create.nut.ts b/test/nuts/create.nut.ts deleted file mode 100644 index 2736fb7b4..000000000 --- a/test/nuts/create.nut.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2021, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as fs from 'fs'; -import { join } from 'path'; -import { expect } from '@salesforce/command/lib/test'; -import { TestSession } from '@salesforce/cli-plugins-testkit'; -import { execCmd } from '@salesforce/cli-plugins-testkit'; -import { Dictionary } from '@salesforce/ts-types'; - -describe('force:source:manifest:create', () => { - let session: TestSession; - const orgAlias = 'smc'; - - before(async () => { - session = await TestSession.create({ - project: { - gitClone: 'https://github.com/trailheadapps/dreamhouse-lwc.git', - }, - devhubAuthStrategy: 'AUTO', - scratchOrgs: [ - { - executable: 'sfdx', - config: join('config', 'project-scratch-def.json'), - alias: orgAlias, - setDefault: true, - wait: 10, - duration: 1, - }, - ], - }); - }); - - after(async () => { - await session?.clean(); - }); - - it('should produce a manifest (package.xml) for ApexClass', () => { - const result = execCmd('force:source:manifest:create --metadata ApexClass --json', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result).to.be.ok; - expect(result).to.include({ path: 'package.xml', name: 'package.xml' }); - }); - - it('should produce a manifest (destructiveChanges.xml) for ApexClass in a new directory', () => { - const apexManifest = - '\n' + - '\n' + - ' \n' + - ' *\n' + - ' ApexClass\n' + - ' \n' + - ' 51.0\n' + - ''; - - const output = join('abc', 'def'); - const outputFile = join(output, 'destructiveChanges.xml'); - const result = execCmd( - `force:source:manifest:create --metadata ApexClass --manifesttype destroy --outputdir ${output} --apiversion=51.0 --json`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(result).to.be.ok; - expect(result).to.include({ path: `${outputFile}`, name: 'destructiveChanges.xml' }); - const file = fs.readFileSync(join(session.project.dir, outputFile), 'utf-8'); - expect(file).to.include(apexManifest); - }); - - it('should produce a custom manifest (myNewManifest.xml) for a sourcepath', () => { - const output = join('abc', 'def'); - const outputFile = join(output, 'myNewManifest.xml'); - const result = execCmd( - `force:source:manifest:create --metadata ApexClass --manifestname myNewManifest --outputdir ${output} --json`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(result).to.be.ok; - expect(result).to.include({ path: `${outputFile}`, name: 'myNewManifest.xml' }); - }); - - it('should produce a manifest in a directory with stdout output', () => { - const output = join('abc', 'def'); - const result = execCmd(`force:source:manifest:create --metadata ApexClass --outputdir ${output}`, { - ensureExitCode: 0, - }).shellOutput; - expect(result).to.include(`successfully wrote package.xml to ${output}`); - }); - - it('should produce a manifest with stdout output', () => { - const result = execCmd('force:source:manifest:create --metadata ApexClass', { - ensureExitCode: 0, - }).shellOutput; - expect(result).to.include('successfully wrote package.xml'); - }); - - it('should produce a manifest from metadata in an org', async () => { - const manifestName = 'org-metadata.xml'; - const result = execCmd(`force:source:manifest:create --fromorg ${orgAlias} -n ${manifestName} --json`, { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result).to.be.ok; - expect(result).to.include({ path: manifestName, name: manifestName }); - const stats = fs.statSync(join(session.project.dir, manifestName)); - expect(stats.isFile()).to.be.true; - expect(stats.size).to.be.greaterThan(100); - }); -}); diff --git a/test/nuts/delete.nut.ts b/test/nuts/delete.nut.ts deleted file mode 100644 index 3a5aee8d2..000000000 --- a/test/nuts/delete.nut.ts +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import { expect } from 'chai'; -import { execCmd } from '@salesforce/cli-plugins-testkit'; -import { SourceTestkit } from '@salesforce/source-testkit'; -import { exec } from 'shelljs'; -import { FileResponse } from '@salesforce/source-deploy-retrieve'; -import { isNameObsolete } from './shared/isNameObsolete'; - -describe('source:delete NUTs', () => { - let testkit: SourceTestkit; - - const queryOrgAndFS = async (name: string, fsPath: string): Promise => { - // ensure the LWC is still in the org - expect(await isNameObsolete(testkit.username, 'LightningComponentBundle', name)).to.be.false; - // while the helper.js file was deleted - expect(fs.existsSync(fsPath)).to.be.false; - }; - - const createApexClass = () => { - // create and deploy an ApexClass that can be deleted without dependency issues - const apexName = 'myApexClass'; - const output = path.join('force-app', 'main', 'default', 'classes'); - const pathToClass = path.join(testkit.projectDir, output, `${apexName}.cls`); - execCmd(`force:apex:class:create --classname ${apexName} --outputdir ${output}`, { ensureExitCode: 0 }); - execCmd(`force:source:deploy -m ApexClass:${apexName}`, { ensureExitCode: 0 }); - return { apexName, output, pathToClass }; - }; - - before(async () => { - testkit = await SourceTestkit.create({ - nut: __filename, - repository: 'https://github.com/trailheadapps/dreamhouse-lwc.git', - }); - execCmd('force:source:deploy --sourcepath force-app', { ensureExitCode: 0 }); - }); - - after(async () => { - await testkit?.clean(); - }); - - it('should source:delete a static resource folder using the sourcepath param', () => { - const pathToSR = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'staticresources'); - const pathToJson = path.join(pathToSR, 'sample_data_properties.json'); - const pathToXml = path.join(pathToSR, 'sample_data_properties.resource-meta.xml'); - const response = execCmd<{ deletedSource: [{ filePath: string }] }>( - `force:source:delete --json --noprompt --sourcepath ${pathToJson}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(response.deletedSource).to.have.length(2); - expect(fs.existsSync(pathToJson)).to.be.false; - expect(fs.existsSync(pathToXml)).to.be.false; - }); - - it('should source:delete an ApexClass using the metadata param', () => { - const { apexName, pathToClass } = createApexClass(); - const response = execCmd<{ deletedSource: [{ filePath: string }] }>( - `force:source:delete --json --noprompt --metadata ApexClass:${apexName}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(response.deletedSource).to.have.length(2); - expect(fs.existsSync(pathToClass)).to.be.false; - }); - - it('should source:delete all Prompts using the sourcepath param', () => { - const response = execCmd<{ deletedSource: [{ filePath: string }] }>( - `force:source:delete --json --noprompt --sourcepath ${path.join('force-app', 'main', 'default', 'prompts')}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - const pathToPrompts = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'prompts'); - expect(response.deletedSource).to.have.length(3); - // should delete directory contents - expect(fs.readdirSync(pathToPrompts).length).to.equal(0); - }); - - it('should source:delete an ApexClass using the sourcepath param', () => { - const { pathToClass } = createApexClass(); - const response = execCmd<{ deletedSource: [{ filePath: string }] }>( - `force:source:delete --json --noprompt --sourcepath ${pathToClass}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(response.deletedSource).to.have.length(2); - expect(fs.existsSync(pathToClass)).to.be.false; - }); - - it('should source:delete a remote-only ApexClass from the org', async () => { - const { apexName, pathToClass } = createApexClass(); - const query = () => JSON.parse( - exec( - `sfdx force:data:soql:query -q "SELECT IsNameObsolete FROM SourceMember WHERE MemberType='ApexClass' AND MemberName='${apexName}' LIMIT 1" -t --json`, - { silent: true } - ) - ) as { result: { records: Array<{ IsNameObsolete: boolean }> } }; - - let soql = query(); - // the ApexClass is present in the org - expect(soql.result.records[0].IsNameObsolete).to.be.false; - await testkit.deleteGlobs(['force-app/main/default/classes/myApexClass.*']); - const response = execCmd<{ deletedSource: [{ filePath: string }] }>( - `force:source:delete --json --noprompt --metadata ApexClass:${apexName}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - // remote only delete won't have an associated filepath - expect(response.deletedSource).to.have.length(0); - expect(fs.existsSync(pathToClass)).to.be.false; - soql = query(); - // the apex class has been deleted in the org - expect(soql.result.records[0].IsNameObsolete).to.be.true; - }); - - it('should NOT delete local files with --checkonly', () => { - const { apexName, pathToClass } = createApexClass(); - const response = execCmd<{ deletedSource: [{ filePath: string }]; deletes: [{ checkOnly: boolean }] }>( - `force:source:delete --json --checkonly --noprompt --metadata ApexClass:${apexName}`, - { - ensureExitCode: 0, - } - ).jsonOutput.result; - expect(response.deletedSource).to.have.length(2); - expect(response.deletes[0].checkOnly).to.be.true; - expect(fs.existsSync(pathToClass)).to.be.true; - }); - - it('should run tests with a delete', async () => { - const { pathToClass, apexName } = createApexClass(); - const response = execCmd<{ - checkOnly: boolean; - runTestsEnabled: boolean; - }>(`force:source:delete --json --testlevel RunAllTestsInOrg --noprompt --metadata ApexClass:${apexName}`, { - ensureExitCode: 1, - }).jsonOutput.result; - // the delete operation will fail due to test failures without the 'dreamhouse' permission set assigned to the user - expect(response.runTestsEnabled).to.be.true; - expect(response.checkOnly).to.be.false; - // ensure a failed delete attempt won't delete local files - expect(fs.existsSync(pathToClass)).to.be.true; - }); - - it('should delete a bundle component and deploy as a "new" bundle', async () => { - // use the brokerCard LWC - const lwcPath = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc', 'brokerCard', 'helper.js'); - fs.writeFileSync(lwcPath, '//', { encoding: 'utf8' }); - execCmd(`force:source:deploy -p ${lwcPath}`); - const deleteResult = execCmd<{ deletedSource: [FileResponse] }>( - `force:source:delete -p ${lwcPath} --noprompt --json` - ).jsonOutput.result; - - expect(deleteResult.deletedSource.length).to.equal(1); - expect(deleteResult.deletedSource[0].filePath, 'filepath').to.include(lwcPath); - expect(deleteResult.deletedSource[0].fullName, 'fullname').to.include(path.join('brokerCard', 'helper.js')); - expect(deleteResult.deletedSource[0].state, 'state').to.equal('Deleted'); - expect(deleteResult.deletedSource[0].type, 'type').to.equal('LightningComponentBundle'); - - await queryOrgAndFS('brokerCard', lwcPath); - }); - - it('should delete a bundle component and deploy as a "new" bundle to two different bundles', async () => { - // use the brokerCard and daysOnMarket LWC each with a helper.js file - const lwcPath1 = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc', 'brokerCard', 'helper.js'); - const lwcPath2 = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc', 'daysOnMarket', 'helper.js'); - fs.writeFileSync(lwcPath1, '//', { encoding: 'utf8' }); - fs.writeFileSync(lwcPath2, '//', { encoding: 'utf8' }); - execCmd(`force:source:deploy -p ${lwcPath1},${lwcPath2}`); - // delete both helper.js files at the same time - const deleteResult = execCmd<{ deletedSource: FileResponse[] }>( - `force:source:delete -p "${lwcPath1},${lwcPath2}" --noprompt --json` - ).jsonOutput.result; - - expect(deleteResult.deletedSource.length).to.equal(2); - expect(deleteResult.deletedSource[0].filePath, 'filepath').to.include(lwcPath1); - expect(deleteResult.deletedSource[0].fullName, 'fullname').to.include(path.join('brokerCard', 'helper.js')); - expect(deleteResult.deletedSource[0].state, 'state').to.equal('Deleted'); - expect(deleteResult.deletedSource[0].type, 'type').to.equal('LightningComponentBundle'); - - expect(deleteResult.deletedSource[1].filePath, 'filepath').to.include(lwcPath2); - expect(deleteResult.deletedSource[1].fullName, 'fullname').to.include(path.join('daysOnMarket', 'helper.js')); - expect(deleteResult.deletedSource[1].state, 'state').to.equal('Deleted'); - expect(deleteResult.deletedSource[1].type, 'type').to.equal('LightningComponentBundle'); - - await queryOrgAndFS('brokerCard', lwcPath1); - await queryOrgAndFS('daysOnMarket', lwcPath2); - }); - - it('should delete an entire LWC', async () => { - const lwcPath = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc'); - const mylwcPath = path.join(lwcPath, 'mylwc'); - execCmd(`force:lightning:component:create -n mylwc --type lwc -d ${lwcPath}`); - execCmd(`force:source:deploy -p ${mylwcPath}`); - expect(await isNameObsolete(testkit.username, 'LightningComponentBundle', 'mylwc')).to.be.false; - const deleteResult = execCmd<{ deletedSource: [FileResponse] }>( - `force:source:delete -p ${mylwcPath} --noprompt --json` - ).jsonOutput.result; - - expect(deleteResult.deletedSource.length).to.equal(3); - expect(deleteResult.deletedSource[0].filePath, 'filepath').to.include(mylwcPath); - expect(deleteResult.deletedSource[0].fullName, 'fullname').to.include(path.join('mylwc')); - expect(deleteResult.deletedSource[0].state, 'state').to.equal('Deleted'); - expect(deleteResult.deletedSource[0].type, 'type').to.equal('LightningComponentBundle'); - - expect(fs.existsSync(mylwcPath)).to.be.false; - expect(await isNameObsolete(testkit.username, 'LightningComponentBundle', 'mylwc')).to.be.true; - }); - - it('a failed delete will NOT delete files locally', async () => { - const lwcPath = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc'); - const brokerPath = path.join(lwcPath, 'brokerCard'); - const deleteResult = execCmd<{ deletedSource: [FileResponse & { error: string }] }>( - `force:source:delete -p ${brokerPath} --noprompt --json`, - { ensureExitCode: 1 } - ).jsonOutput.result; - - expect(deleteResult.deletedSource.length).to.equal(1); - expect(deleteResult.deletedSource[0].fullName, 'fullname').to.include(path.join('brokerCard')); - expect(deleteResult.deletedSource[0].state, 'state').to.equal('Failed'); - expect(deleteResult.deletedSource[0].type, 'type').to.equal('LightningComponentBundle'); - expect(deleteResult.deletedSource[0].error, 'error').to.include( - 'Referenced by a component instance inside the Lightning page Property Record Page : Lightning Page.' - ); - - expect(await isNameObsolete(testkit.username, 'LightningComponentBundle', 'brokerCard')).to.be.false; - expect(fs.existsSync(brokerPath)).to.be.true; - }); -}); diff --git a/test/nuts/deployDestructive.nut.ts b/test/nuts/deployDestructive.nut.ts index ae854d56b..735d0f1ab 100644 --- a/test/nuts/deployDestructive.nut.ts +++ b/test/nuts/deployDestructive.nut.ts @@ -10,6 +10,7 @@ import { expect } from 'chai'; import { execCmd } from '@salesforce/cli-plugins-testkit'; import { SourceTestkit } from '@salesforce/source-testkit'; import { isNameObsolete } from './shared/isNameObsolete'; +import { cliForManifestCreate } from './shared/cliForManifestCreate'; describe('source:deploy --destructive NUTs', () => { let testkit: SourceTestkit; @@ -26,6 +27,7 @@ describe('source:deploy --destructive NUTs', () => { const createManifest = (metadata: string, manifesttype: string) => { execCmd(`force:source:manifest:create --metadata ${metadata} --manifesttype ${manifesttype}`, { ensureExitCode: 0, + cli: cliForManifestCreate, }); }; diff --git a/test/nuts/digitalExperienceBundle/constants.ts b/test/nuts/digitalExperienceBundle/constants.ts new file mode 100644 index 000000000..bf8353d27 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/constants.ts @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import { join, sep } from 'path'; +import { TestSessionOptions } from '@salesforce/cli-plugins-testkit/lib/testSession'; +import { registry } from '@salesforce/source-deploy-retrieve'; +import { META_XML_SUFFIX } from '@salesforce/source-deploy-retrieve/lib/src/common'; + +export const SOURCE_BASE_RELATIVE_PATH = join('force-app', 'main', 'default'); +export const DEB_NUTS_PATH = join(process.cwd(), 'test', 'nuts', 'digitalExperienceBundle'); + +export const TYPES = { + DEB: registry.types.digitalexperiencebundle, + DE: registry.types.digitalexperiencebundle.children.types.digitalexperience, + DEC: registry.types.digitalexperienceconfig, + NETWORK: registry.types.network, + CUSTOM_SITE: registry.types.customsite, + APEX_PAGE: registry.types.apexpage, + APEX_CLASS: registry.types.apexclass, +} as const; + +export const DIR_NAMES = { + PROJECT: 'project', + STORE: 'store', + COMPONENTS: 'components', + MANIFESTS: 'manifests', + NETWORKS: TYPES.NETWORK.directoryName, + SITES: TYPES.CUSTOM_SITE.directoryName, + DIGITAL_EXPERIENCE_CONFIGS: TYPES.DEC.directoryName, + DIGITAL_EXPERIENCES: TYPES.DEB.directoryName, + SITE: 'site', + HOME: 'home', + DEB_A: 'Capricorn_Coffee_A1', + DEB_B: 'Capricorn_Coffee_B1', + DE_VIEW: 'sfdc_cms__view', + DE_ROUTE: 'sfdc_cms__route', + VIEW_DOCUMENT_DETAIL: 'documentDetail', + ROUTE_DOCUMENT_DETAIL: 'Document_Detail__c', +} as const; + +export const DEBS_RELATIVE_PATH = join(SOURCE_BASE_RELATIVE_PATH, DIR_NAMES.DIGITAL_EXPERIENCES, DIR_NAMES.SITE); +export const DEB_A_RELATIVE_PATH = join(DEBS_RELATIVE_PATH, DIR_NAMES.DEB_A); +export const DEB_B_RELATIVE_PATH = join(DEBS_RELATIVE_PATH, DIR_NAMES.DEB_B); + +export const STORE_PATH = join(DEB_NUTS_PATH, DIR_NAMES.STORE); +export const STORE_COMPONENTS_PATH = join(STORE_PATH, DIR_NAMES.COMPONENTS); +export const STORE_MANIFESTS_PATH = join(STORE_PATH, DIR_NAMES.MANIFESTS); + +export const FULL_NAMES = { + DEB_A: join(DIR_NAMES.SITE, DIR_NAMES.DEB_A), + DEB_B: join(DIR_NAMES.SITE, DIR_NAMES.DEB_B), + DE_VIEW_HOME_A: join(DIR_NAMES.SITE, `${DIR_NAMES.DEB_A}.${DIR_NAMES.DE_VIEW}`, DIR_NAMES.HOME), + DE_VIEW_HOME_B: join(DIR_NAMES.SITE, `${DIR_NAMES.DEB_B}.${DIR_NAMES.DE_VIEW}`, DIR_NAMES.HOME), + DE_VIEW_DOCUMENT_DETAIL_A: join( + DIR_NAMES.SITE, + `${DIR_NAMES.DEB_A}.${DIR_NAMES.DE_VIEW}`, + DIR_NAMES.VIEW_DOCUMENT_DETAIL + ), + DE_ROUTE_DOCUMENT_DETAIL_A: join( + DIR_NAMES.SITE, + `${DIR_NAMES.DEB_A}.${DIR_NAMES.DE_ROUTE}`, + DIR_NAMES.ROUTE_DOCUMENT_DETAIL + ), +} as const; + +export const FILE_NAMES = { + CONTENT: { + DE_MAIN: 'content.json', + DE_FRENCH_VARIANT: 'fr.json', + }, + META: { + DEB_A: `${DIR_NAMES.DEB_A}.${TYPES.DEB.suffix}${META_XML_SUFFIX}`, + DEB_B: `${DIR_NAMES.DEB_B}.${TYPES.DEB.suffix}${META_XML_SUFFIX}`, + DE: TYPES.DE.metaFileSuffix, // metaFileName = metaFileSuffix in case of DigitalExperience + }, +} as const; + +export const DIR_RELATIVE_PATHS = { + NETWORKS: join(SOURCE_BASE_RELATIVE_PATH, DIR_NAMES.NETWORKS), + SITES: join(SOURCE_BASE_RELATIVE_PATH, DIR_NAMES.SITES), + DIGITAL_EXPERIENCE_CONFIGS: join(SOURCE_BASE_RELATIVE_PATH, DIR_NAMES.DIGITAL_EXPERIENCE_CONFIGS), + DE_VIEW_A: join(DEB_A_RELATIVE_PATH, DIR_NAMES.DE_VIEW), + DE_VIEW_B: join(DEB_B_RELATIVE_PATH, DIR_NAMES.DE_VIEW), + DE_ROUTE_A: join(DEB_A_RELATIVE_PATH, DIR_NAMES.DE_ROUTE), + DE_ROUTE_B: join(DEB_B_RELATIVE_PATH, DIR_NAMES.DE_ROUTE), + DE_VIEW_HOME_A: join(DEB_A_RELATIVE_PATH, DIR_NAMES.DE_VIEW, DIR_NAMES.HOME), + DE_VIEW_HOME_B: join(DEB_B_RELATIVE_PATH, DIR_NAMES.DE_VIEW, DIR_NAMES.HOME), + DE_VIEW_DOCUMENT_DETAIL_A: join(DEB_A_RELATIVE_PATH, DIR_NAMES.DE_VIEW, DIR_NAMES.VIEW_DOCUMENT_DETAIL), + DE_ROUTE_DOCUMENT_DETAIL_A: join(DEB_A_RELATIVE_PATH, DIR_NAMES.DE_ROUTE, DIR_NAMES.ROUTE_DOCUMENT_DETAIL), +} as const; + +export const FILE_RELATIVE_PATHS = { + DEB_META_A: join(DEB_A_RELATIVE_PATH, FILE_NAMES.META.DEB_A), + DEB_META_B: join(DEB_B_RELATIVE_PATH, FILE_NAMES.META.DEB_B), + DE_VIEW_HOME_META_A: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_A, FILE_NAMES.META.DE), + DE_VIEW_HOME_META_B: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_B, FILE_NAMES.META.DE), + DE_VIEW_HOME_CONTENT_A: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_A, FILE_NAMES.CONTENT.DE_MAIN), + DE_VIEW_HOME_CONTENT_B: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_B, FILE_NAMES.CONTENT.DE_MAIN), + DE_VIEW_HOME_FR_VARIANT_A: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_A, FILE_NAMES.CONTENT.DE_FRENCH_VARIANT), + DE_VIEW_HOME_FR_VARIANT_B: join(DIR_RELATIVE_PATHS.DE_VIEW_HOME_B, FILE_NAMES.CONTENT.DE_FRENCH_VARIANT), + DE_VIEW_DOCUMENT_DETAIL_META_A: join(DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A, FILE_NAMES.META.DE), + DE_VIEW_DOCUMENT_DETAIL_CONTENT_A: join(DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A, FILE_NAMES.CONTENT.DE_MAIN), + DE_ROUTE_DOCUMENT_DETAIL_META_A: join(DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A, FILE_NAMES.META.DE), + DE_ROUTE_DOCUMENT_DETAIL_CONTENT_A: join(DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A, FILE_NAMES.CONTENT.DE_MAIN), +} as const; + +export const STORE = { + COMPONENTS: { + DE_VIEW_DOCUMENT_DETAIL: join(STORE_COMPONENTS_PATH, DIR_NAMES.DE_VIEW, DIR_NAMES.VIEW_DOCUMENT_DETAIL), + DE_ROUTE_DOCUMENT_DETAIL: join(STORE_COMPONENTS_PATH, DIR_NAMES.DE_ROUTE, DIR_NAMES.ROUTE_DOCUMENT_DETAIL), + }, + MANIFESTS: { + ALL_DEBS: join(STORE_MANIFESTS_PATH, 'all-debs-package.xml'), + ALL_DE: join(STORE_MANIFESTS_PATH, 'all-de-package.xml'), + ALL_DE_OF_DEB_A: join(STORE_MANIFESTS_PATH, 'all-de-of-deb-a-package.xml'), + FULL_SITE_DEB_A_AND_B: join(STORE_MANIFESTS_PATH, 'full-site-deb-a-and-b-package.xml'), + JUST_DEB_A: join(STORE_MANIFESTS_PATH, 'just-deb-a-package.xml'), + DE_VIEW_HOME_OF_DEB_A: join(STORE_MANIFESTS_PATH, 'de-view-home-of-deb-a-package.xml'), + DE_DOCUMENT_DETAIL_PAGE_A: join(STORE_MANIFESTS_PATH, 'de-document-detail-page-a-package.xml'), + EMPTY_PACKAGE_XML: join(STORE_MANIFESTS_PATH, 'empty-package.xml'), + ALL_DEBS_SOURCE_PATH_GEN: 'all-debs-sourcepath-gen-package.xml', + ALL_DEBS_METADATA_GEN: 'all-debs-metadata-gen-package.xml', + }, +} as const; + +export const METADATA = { + ALL_DEBS: TYPES.DEB.name, + ALL_DE: TYPES.DE.name, + ALL_DE_OF_DEB_B: `${TYPES.DE.name}:${DIR_NAMES.SITE}${sep}${DIR_NAMES.DEB_B}.*`, + FULL_SITE_DEB_A_AND_B: `${TYPES.DEB.name},${TYPES.DEC.name},${TYPES.NETWORK.name},${TYPES.CUSTOM_SITE.name}`, + JUST_DEB_B: `${TYPES.DEB.name}:${FULL_NAMES.DEB_B}`, + DE_VIEW_HOME_OF_DEB_B: `${TYPES.DE.name}:${FULL_NAMES.DE_VIEW_HOME_B}`, + DE_DOCUMENT_DETAIL_PAGE_A: `${TYPES.DE.name}:${FULL_NAMES.DE_VIEW_DOCUMENT_DETAIL_A},${TYPES.DE.name}:${FULL_NAMES.DE_ROUTE_DOCUMENT_DETAIL_A}`, +}; + +export const TEST_SESSION_OPTIONS: TestSessionOptions = { + project: { + sourceDir: join(DEB_NUTS_PATH, DIR_NAMES.PROJECT), + }, + devhubAuthStrategy: 'AUTO', + scratchOrgs: [ + { + executable: 'sfdx', + duration: 1, + setDefault: true, + wait: 10, + config: join('config', 'project-scratch-def.json'), + }, + ], +}; diff --git a/test/nuts/digitalExperienceBundle/deb.manifest.nut.ts b/test/nuts/digitalExperienceBundle/deb.manifest.nut.ts new file mode 100644 index 000000000..b6239e48b --- /dev/null +++ b/test/nuts/digitalExperienceBundle/deb.manifest.nut.ts @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import * as fs from 'fs'; +import { join } from 'path'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { expect } from 'chai'; +import { beforeEach } from 'mocha'; +import { DeployCommandResult } from '../../../lib/formatters/deployResultFormatter'; +import { RetrieveCommandResult } from '../../../lib/formatters/retrieveResultFormatter'; +import { DEBS_RELATIVE_PATH, FULL_NAMES, METADATA, STORE, TEST_SESSION_OPTIONS, TYPES } from './constants'; +import { + assertAllDEBAndTheirDECounts, + assertDECountOfSingleDEB, + assertDECountsOfAllDEB, + assertDocumentDetailPageA, + assertDocumentDetailPageADelete, + assertSingleDEBAndItsDECounts, + assertViewHome, + createDocumentDetailPageAInLocal, + deleteLocalSource, +} from './helper'; + +describe('deb -- manifest option', () => { + let session: TestSession; + + before(async () => { + session = await TestSession.create(TEST_SESSION_OPTIONS); + }); + + after(async () => { + await session?.clean(); + }); + + // skip while manifest create moves to plugin-deploy-retrieve + describe.skip('generate manifest', () => { + it('should generate manifest for all debs using sourcepath', () => { + execCmd( + `force:source:manifest:create --sourcepath ${DEBS_RELATIVE_PATH} --manifestname ${STORE.MANIFESTS.ALL_DEBS_SOURCE_PATH_GEN} --json`, + { ensureExitCode: 0 } + ); + expect(fs.existsSync(join(session.project.dir, STORE.MANIFESTS.ALL_DEBS_SOURCE_PATH_GEN))).to.be.true; + }); + + it('should generate manifest for all debs using metadata', () => { + execCmd( + `force:source:manifest:create --metadata ${METADATA.ALL_DEBS} --manifestname ${STORE.MANIFESTS.ALL_DEBS_METADATA_GEN} --json`, + { ensureExitCode: 0 } + ); + expect(fs.existsSync(join(session.project.dir, STORE.MANIFESTS.ALL_DEBS_METADATA_GEN))).to.be.true; + }); + }); + + describe('deploy', () => { + before(() => { + execCmd( + `force:source:deploy --metadata ${TYPES.APEX_PAGE.name},${TYPES.APEX_CLASS.name} --json`, + { + ensureExitCode: 0, + } + ); + }); + + it('should deploy complete enhanced lwr sites deb_a and deb_b (including de config, network and customsite)', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.FULL_SITE_DEB_A_AND_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource, 6); + }); + + describe('individual metadata type', () => { + it('should deploy deb type (all debs - deb_a and deb_b)', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.ALL_DEBS} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource); + }); + + it('should deploy de type (all de components of deb_a and deb_b)', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.ALL_DE} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDECountsOfAllDEB(deployedSource); + }); + }); + + describe('individual metadata item', () => { + it('should deploy all de components of deb_a', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.ALL_DE_OF_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDECountOfSingleDEB(deployedSource); + }); + + it('should deploy just deb_a', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.JUST_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertSingleDEBAndItsDECounts(deployedSource, FULL_NAMES.DEB_A); + }); + + it('should deploy de_view_home of deb_a', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.DE_VIEW_HOME_OF_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertViewHome(deployedSource, 'a'); + }); + }); + + // skip while manifest create moves to plugin-deploy-retrieve + describe.skip('through generated manifests', () => { + it('should deploy all debs using the manifest generated by sourcepath', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.ALL_DEBS_SOURCE_PATH_GEN} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource); + }); + + it('should deploy all debs using the manifest generated by metadata', () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.ALL_DEBS_METADATA_GEN} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource); + }); + }); + }); + + describe('retrieve (without local metadata)', () => { + beforeEach(async () => { + await deleteLocalSource(DEBS_RELATIVE_PATH, session.project.dir); + }); + + describe('individual metadata type', () => { + it('should retrieve deb type (all debs - deb_a and deb_b)', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.ALL_DEBS} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertAllDEBAndTheirDECounts(inboundFiles); + }); + + it('should retrieve de type (all de components of deb_a and deb_b)', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.ALL_DE} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertDECountsOfAllDEB(inboundFiles); + }); + }); + + describe('individual metadata item', () => { + it('should retrieve all de components of deb_a', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.ALL_DE_OF_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertDECountOfSingleDEB(inboundFiles); + }); + + it('should retrieve just deb_a', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.JUST_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertSingleDEBAndItsDECounts(inboundFiles, FULL_NAMES.DEB_A); + }); + + it('should retrieve de_view_home of deb_a', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.DE_VIEW_HOME_OF_DEB_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertViewHome(inboundFiles, 'a'); + }); + }); + + // skip while manifest create moves to plugin-deploy-retrieve + describe.skip('through generated manifests', () => { + it('should retrieve all debs using the manifest generated by sourcepath', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.ALL_DEBS_SOURCE_PATH_GEN} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertAllDEBAndTheirDECounts(inboundFiles); + }); + + it('should retrieve all debs using the manifest generated by metadata', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --manifest ${STORE.MANIFESTS.ALL_DEBS_METADATA_GEN} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertAllDEBAndTheirDECounts(inboundFiles); + }); + }); + }); + + describe('new site page', () => { + it('should deploy new page (view and route de components) of deb_a', async () => { + createDocumentDetailPageAInLocal(session.project.dir); + + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.DE_DOCUMENT_DETAIL_PAGE_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDocumentDetailPageA(deployedSource); + }); + + it('should delete new page (view and route de components) of deb_a', async () => { + const deployedSource = execCmd( + `force:source:deploy --manifest ${STORE.MANIFESTS.EMPTY_PACKAGE_XML} --predestructivechanges ${STORE.MANIFESTS.DE_DOCUMENT_DETAIL_PAGE_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDocumentDetailPageA(deployedSource); + await assertDocumentDetailPageADelete(session, false); + }); + }); +}); diff --git a/test/nuts/digitalExperienceBundle/deb.metadata.nut.ts b/test/nuts/digitalExperienceBundle/deb.metadata.nut.ts new file mode 100644 index 000000000..81e3631b6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/deb.metadata.nut.ts @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { beforeEach } from 'mocha'; +import { DeployCommandResult } from '../../../lib/formatters/deployResultFormatter'; +import { RetrieveCommandResult } from '../../../lib/formatters/retrieveResultFormatter'; +import { DEBS_RELATIVE_PATH, FULL_NAMES, METADATA, TEST_SESSION_OPTIONS, TYPES } from './constants'; +import { + assertAllDEBAndTheirDECounts, + assertDECountOfSingleDEB, + assertDECountsOfAllDEB, + assertDocumentDetailPageA, + assertDocumentDetailPageADelete, + assertSingleDEBAndItsDECounts, + assertViewHome, + createDocumentDetailPageAInLocal, + deleteLocalSource, +} from './helper'; + +describe('deb -- metadata option', () => { + let session: TestSession; + + before(async () => { + session = await TestSession.create(TEST_SESSION_OPTIONS); + }); + + after(async () => { + await session?.clean(); + }); + + describe('deploy', () => { + before(() => { + execCmd( + `force:source:deploy --metadata ${TYPES.APEX_PAGE.name},${TYPES.APEX_CLASS.name} --json`, + { + ensureExitCode: 0, + } + ); + }); + + it('should deploy complete enhanced lwr sites deb_a and deb_b (including de config, network and customsite)', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.FULL_SITE_DEB_A_AND_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource, 6); + }); + + describe('individual metadata type', () => { + it('should deploy deb type (all debs - deb_a and deb_b)', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.ALL_DEBS} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource); + }); + + it('should deploy de type (all de components of deb_a and deb_b)', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.ALL_DE} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDECountsOfAllDEB(deployedSource); + }); + }); + + describe('individual metadata item', () => { + it('should deploy all de components of deb_b', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.ALL_DE_OF_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDECountOfSingleDEB(deployedSource); + }); + + it('should deploy just deb_b', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.JUST_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertSingleDEBAndItsDECounts(deployedSource, FULL_NAMES.DEB_B); + }); + + it('should deploy de_view_home of deb_b', () => { + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.DE_VIEW_HOME_OF_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertViewHome(deployedSource, 'b'); + }); + }); + }); + + describe('retrieve (without local metadata)', () => { + beforeEach(async () => { + await deleteLocalSource(DEBS_RELATIVE_PATH, session.project.dir); + }); + + describe('individual metadata type', () => { + it('should retrieve deb type (all debs - deb_a and deb_b)', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --metadata ${METADATA.ALL_DEBS} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertAllDEBAndTheirDECounts(inboundFiles); + }); + + it('should retrieve de type (all de components of deb_a and deb_b)', () => { + const inboundFiles = execCmd( + `force:source:retrieve --metadata ${METADATA.ALL_DE} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertDECountsOfAllDEB(inboundFiles); + }); + }); + + describe('individual metadata item', () => { + it('should retrieve all de components of deb_b', () => { + const inboundFiles = execCmd( + `force:source:retrieve --metadata ${METADATA.ALL_DE_OF_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertDECountOfSingleDEB(inboundFiles); + }); + + it('should retrieve just deb_b', () => { + const inboundFiles = execCmd( + `force:source:retrieve --metadata ${METADATA.JUST_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertSingleDEBAndItsDECounts(inboundFiles, FULL_NAMES.DEB_B); + }); + + it('should retrieve de_view_home of deb_b', () => { + const inboundFiles = execCmd( + `force:source:retrieve --metadata ${METADATA.DE_VIEW_HOME_OF_DEB_B} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertViewHome(inboundFiles, 'b'); + }); + }); + }); + + describe('new site page', () => { + it('should deploy new page (view and route de components) of deb_a', async () => { + createDocumentDetailPageAInLocal(session.project.dir); + + const deployedSource = execCmd( + `force:source:deploy --metadata ${METADATA.DE_DOCUMENT_DETAIL_PAGE_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDocumentDetailPageA(deployedSource); + }); + + // skip until plugin-deploy-retrieve publishes + it.skip('should delete the page (view and route de components) of deb_a', async () => { + const deletedSource = execCmd( + `force:source:delete --metadata ${METADATA.DE_DOCUMENT_DETAIL_PAGE_A} --noprompt --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deletedSource; + + assertDocumentDetailPageA(deletedSource); + await assertDocumentDetailPageADelete(session, true); + }); + }); +}); diff --git a/test/nuts/digitalExperienceBundle/deb.sourcepath.nut.ts b/test/nuts/digitalExperienceBundle/deb.sourcepath.nut.ts new file mode 100644 index 000000000..fcdb35c94 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/deb.sourcepath.nut.ts @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +// import * as fs from 'fs'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { DeployCommandResult } from '../../../lib/formatters/deployResultFormatter'; +import { RetrieveCommandResult } from '../../../lib/formatters/retrieveResultFormatter'; +import { + DEB_A_RELATIVE_PATH, + DEBS_RELATIVE_PATH, + DIR_RELATIVE_PATHS, + FULL_NAMES, + TEST_SESSION_OPTIONS, + TYPES, +} from './constants'; +import { + assertAllDEBAndTheirDECounts, + assertDocumentDetailPageA, + assertDocumentDetailPageADelete, + assertSingleDEBAndItsDECounts, + assertViewHome, + createDocumentDetailPageAInLocal, +} from './helper'; + +describe('deb -- sourcepath option', () => { + let session: TestSession; + + before(async () => { + session = await TestSession.create(TEST_SESSION_OPTIONS); + }); + + after(async () => { + await session?.clean(); + }); + + describe('deploy', () => { + before(() => { + execCmd( + `force:source:deploy --metadata ${TYPES.APEX_PAGE.name},${TYPES.APEX_CLASS.name} --json`, + { + ensureExitCode: 0, + } + ); + }); + + it('should deploy complete enhanced lwr sites deb_a and deb_b (including de config, network and customsite)', () => { + const deployedSource = execCmd( + `force:source:deploy --sourcepath ${DEBS_RELATIVE_PATH},${DIR_RELATIVE_PATHS.DIGITAL_EXPERIENCE_CONFIGS},${DIR_RELATIVE_PATHS.NETWORKS},${DIR_RELATIVE_PATHS.SITES} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource, 6); + }); + + describe('individual metadata type', () => { + it('should deploy deb type (all debs - deb_a and deb_b)', () => { + const deployedSource = execCmd( + `force:source:deploy --sourcepath ${DEBS_RELATIVE_PATH} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertAllDEBAndTheirDECounts(deployedSource); + }); + }); + + describe('individual metadata item', () => { + it('should deploy just deb_a', () => { + const deployedSource = execCmd( + `force:source:deploy --sourcepath ${DEB_A_RELATIVE_PATH} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertSingleDEBAndItsDECounts(deployedSource, FULL_NAMES.DEB_A); + }); + + it('should deploy de_view_home of deb_a', () => { + const deployedSource = execCmd( + `force:source:deploy --sourcepath ${DIR_RELATIVE_PATHS.DE_VIEW_HOME_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertViewHome(deployedSource, 'a'); + }); + }); + }); + + describe('retrieve', () => { + describe('individual metadata type', () => { + it('should retrieve deb type (all debs - deb_a and deb_b)', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --sourcepath ${DEBS_RELATIVE_PATH} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertAllDEBAndTheirDECounts(inboundFiles); + }); + }); + + describe('individual metadata item', () => { + it('should retrieve just deb_a', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --sourcepath ${DEB_A_RELATIVE_PATH} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertSingleDEBAndItsDECounts(inboundFiles, FULL_NAMES.DEB_A); + }); + + it('should retrieve de_view_home of deb_a', async () => { + const inboundFiles = execCmd( + `force:source:retrieve --sourcepath ${DIR_RELATIVE_PATHS.DE_VIEW_HOME_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.inboundFiles; + + assertViewHome(inboundFiles, 'a'); + }); + }); + }); + + describe('new site page', () => { + it('should deploy new page (view and route de components) of deb_a', async () => { + createDocumentDetailPageAInLocal(session.project.dir); + + const deployedSource = execCmd( + `force:source:deploy --sourcepath ${DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A},${DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A} --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deployedSource; + + assertDocumentDetailPageA(deployedSource); + }); + + // skip until plugin-deploy-retrieve publishes + it.skip('should delete the page (view and route de components) of deb_a', async () => { + const deletedSource = execCmd( + `force:source:delete --sourcepath ${DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A},${DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A} --noprompt --json`, + { + ensureExitCode: 0, + } + ).jsonOutput.result.deletedSource; + + assertDocumentDetailPageA(deletedSource); + await assertDocumentDetailPageADelete(session, true); + }); + }); +}); diff --git a/test/nuts/digitalExperienceBundle/deb.tracking.nut.ts b/test/nuts/digitalExperienceBundle/deb.tracking.nut.ts new file mode 100644 index 000000000..502764487 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/deb.tracking.nut.ts @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import * as fs from 'fs'; +import { join } from 'path'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { expect } from 'chai'; +import { PushResponse } from '../../../src/formatters/source/pushResultFormatter'; +import { StatusResult } from '../../../src/formatters/source/statusFormatter'; +// import { SourceTrackingClearResult } from '../../../src/commands/force/source/tracking/clear'; +// import { PullResponse } from '../../../src/formatters/source/pullFormatter'; +import { FILE_RELATIVE_PATHS, TEST_SESSION_OPTIONS, TYPES } from './constants'; +import { + assertAllDEBAndTheirDECounts, + assertDEBMeta, + assertDocumentDetailPageA, + assertDocumentDetailPageADelete, + assertNoLocalChanges, + assertViewHome, + assertViewHomeStatus, + createDocumentDetailPageAInLocal, + deleteDocumentDetailPageAInLocal, +} from './helper'; + +describe('deb -- tracking/push/pull', () => { + let session: TestSession; + + before(async () => { + session = await TestSession.create(TEST_SESSION_OPTIONS); + }); + + after(async () => { + await session?.clean(); + }); + + it('should push the whole project', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertAllDEBAndTheirDECounts(pushedSource, 10); + }); + + it('should see local change in deb_b', async () => { + const debMetaFilePathB = join(session.project.dir, FILE_RELATIVE_PATHS.DEB_META_B); + const original = await fs.promises.readFile(debMetaFilePathB, 'utf8'); + await fs.promises.writeFile(debMetaFilePathB, original.replace('meta space b', 'meta space b updated')); + + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + assertDEBMeta(statusResult, 'b'); + }); + + it('should push local change in deb_b', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertDEBMeta(pushedSource, 'b'); + assertNoLocalChanges(); + }); + + it('should see local change in de_view_home_content of deb_b', async () => { + const deViewHomeContentFilePathB = join(session.project.dir, FILE_RELATIVE_PATHS.DE_VIEW_HOME_CONTENT_B); + const original = await fs.promises.readFile(deViewHomeContentFilePathB, 'utf8'); + await fs.promises.writeFile( + deViewHomeContentFilePathB, + original.replace('Start Building Your Page', 'Start Building Your Page Updated') + ); + + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + assertViewHomeStatus(statusResult, 'b', 'content'); + }); + + it('should push local change in de_view_home_content of deb_b', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertViewHome(pushedSource, 'b'); + assertNoLocalChanges(); + }); + + it('should see local change in de_view_home_meta of deb_b', async () => { + const deViewHomeMetaFilePathB = join(session.project.dir, FILE_RELATIVE_PATHS.DE_VIEW_HOME_META_B); + await fs.promises.writeFile( + deViewHomeMetaFilePathB, + '{"apiName" : "home", "path" : "views", "type" : "sfdc_cms__view"}' + ); + + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + assertViewHomeStatus(statusResult, 'b', 'meta'); + }); + + it('should push local change in de_view_home_meta of deb_b', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertViewHome(pushedSource, 'b'); + assertNoLocalChanges(); + }); + + // TODO: restore test once it can use tracking:clear from PDR + // it('should pull all debs after clearing source tracking info', () => { + // execCmd('force:source:tracking:clear --noprompt', { + // ensureExitCode: 0, + // }); + + // const pulledSource = execCmd('force:source:pull --forceoverwrite --json', { + // ensureExitCode: 0, + // }).jsonOutput.result.pulledSource; + + // assertAllDEBAndTheirDECounts(pulledSource, 0, false); + // }); + + it('should not see any local/remote changes in deb/de', () => { + const statusResult = execCmd('force:source:status --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + expect(statusResult.every((s) => s.type !== TYPES.DE.name && s.type !== TYPES.DEB.name)).to.be.true; + }); + + describe('new site page', () => { + it('should see locally added page (view and route de components) in deb_a', async () => { + createDocumentDetailPageAInLocal(session.project.dir); + + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + assertDocumentDetailPageA(statusResult); + }); + + it('should push locally added page (view and route de components) in deb_a', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertDocumentDetailPageA(pushedSource); + assertNoLocalChanges(); + }); + + it('should see locally deleted page (view and route de components) in deb_a', async () => { + await deleteDocumentDetailPageAInLocal(session.project.dir); + + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + + assertDocumentDetailPageA(statusResult); + }); + + it('should push local delete change in deb_a [locally deleted page (view and route de components)]', async () => { + const pushedSource = execCmd('force:source:push --json', { + ensureExitCode: 0, + }).jsonOutput.result.pushedSource; + + assertDocumentDetailPageA(pushedSource); + assertNoLocalChanges(); + + await assertDocumentDetailPageADelete(session, false); + }); + }); +}); diff --git a/test/nuts/digitalExperienceBundle/helper.ts b/test/nuts/digitalExperienceBundle/helper.ts new file mode 100644 index 000000000..997f8a6dd --- /dev/null +++ b/test/nuts/digitalExperienceBundle/helper.ts @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { join, relative } from 'path'; +import * as fs from 'fs'; +import { FileResponse } from '@salesforce/source-deploy-retrieve'; +import { expect } from 'chai'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { StatusResult } from '../../../src/formatters/source/statusFormatter'; +import { isNameObsolete } from '../shared/isNameObsolete'; +import { DIR_RELATIVE_PATHS, FILE_RELATIVE_PATHS, FULL_NAMES, STORE, TYPES } from './constants'; + +type CustomFileResponses = Array>; + +export function assertAllDEBAndTheirDECounts( + resp: CustomFileResponses, + otherComponentsCount = 0, + assertTotalCount = true +) { + if (assertTotalCount) expect(resp).to.have.length(104 + otherComponentsCount); + + expect( + resp.reduce( + (acc: [number, number, number, number], curr: FileResponse) => { + if (curr.type === TYPES.DE.name && curr.fullName.includes(FULL_NAMES.DEB_A)) acc[0]++; + if (curr.type === TYPES.DE.name && curr.fullName.includes(FULL_NAMES.DEB_B)) acc[1]++; + if (curr.type === TYPES.DEB.name && curr.fullName === FULL_NAMES.DEB_A) acc[2]++; + if (curr.type === TYPES.DEB.name && curr.fullName === FULL_NAMES.DEB_B) acc[3]++; + return acc; + }, + [0, 0, 0, 0] + ), + JSON.stringify(resp) + ).to.deep.equal([51, 51, 1, 1]); +} + +export function assertSingleDEBAndItsDECounts(resp: CustomFileResponses, debFullName: string) { + expect(resp).to.have.length(52); + expect( + resp.reduce( + (acc: [number, number], curr: FileResponse) => { + if (curr.type === TYPES.DE.name && curr.fullName.includes(debFullName)) acc[0]++; + if (curr.type === TYPES.DEB.name && curr.fullName === debFullName) acc[1]++; + return acc; + }, + [0, 0] + ), + JSON.stringify(resp) + ).to.deep.equal([51, 1]); +} + +export function assertDECountsOfAllDEB(resp: CustomFileResponses) { + expect(resp).to.have.length(102); + expect( + resp.reduce( + (acc: [number, number], curr: FileResponse) => { + if (curr.type === TYPES.DE.name && curr.fullName.includes(FULL_NAMES.DEB_A)) acc[0]++; + if (curr.type === TYPES.DE.name && curr.fullName.includes(FULL_NAMES.DEB_B)) acc[1]++; + return acc; + }, + [0, 0] + ), + JSON.stringify(resp) + ).to.deep.equal([51, 51]); +} + +export function assertDECountOfSingleDEB(resp: CustomFileResponses) { + expect(resp).to.have.length(51); + expect(resp.every((s) => s.type === TYPES.DE.name)).to.be.true; +} + +export function assertDEBMeta(resp: CustomFileResponses, deb: 'a' | 'b') { + expect(resp).to.have.length(1); + + resp[0].filePath = relative(process.cwd(), resp[0].filePath); + + expect(resp[0]).to.include({ + type: TYPES.DEB.name, + fullName: deb === 'a' ? FULL_NAMES.DEB_A : FULL_NAMES.DEB_B, + filePath: deb === 'a' ? FILE_RELATIVE_PATHS.DEB_META_A : FILE_RELATIVE_PATHS.DEB_META_B, + }); +} + +export function assertViewHome(resp: CustomFileResponses, deb: 'a' | 'b') { + expect(resp).to.have.length(3); + expect( + resp.map((s) => ({ + type: s.type, + fullName: s.fullName, + filePath: relative(process.cwd(), s.filePath), + })) + ).to.have.deep.members([ + { + type: TYPES.DE.name, + fullName: deb === 'a' ? FULL_NAMES.DE_VIEW_HOME_A : FULL_NAMES.DE_VIEW_HOME_B, + filePath: deb === 'a' ? FILE_RELATIVE_PATHS.DE_VIEW_HOME_CONTENT_A : FILE_RELATIVE_PATHS.DE_VIEW_HOME_CONTENT_B, + }, + { + type: TYPES.DE.name, + fullName: deb === 'a' ? FULL_NAMES.DE_VIEW_HOME_A : FULL_NAMES.DE_VIEW_HOME_B, + filePath: + deb === 'a' ? FILE_RELATIVE_PATHS.DE_VIEW_HOME_FR_VARIANT_A : FILE_RELATIVE_PATHS.DE_VIEW_HOME_FR_VARIANT_B, + }, + { + type: TYPES.DE.name, + fullName: deb === 'a' ? FULL_NAMES.DE_VIEW_HOME_A : FULL_NAMES.DE_VIEW_HOME_B, + filePath: deb === 'a' ? FILE_RELATIVE_PATHS.DE_VIEW_HOME_META_A : FILE_RELATIVE_PATHS.DE_VIEW_HOME_META_B, + }, + ]); +} + +export function assertViewHomeStatus(resp: CustomFileResponses, deb: 'a' | 'b', type: 'content' | 'meta') { + expect(resp).to.have.length(1); + + resp[0].filePath = relative(process.cwd(), resp[0].filePath); + + expect(resp[0]).to.include({ + type: TYPES.DE.name, + fullName: deb === 'a' ? FULL_NAMES.DE_VIEW_HOME_A : FULL_NAMES.DE_VIEW_HOME_B, + filePath: + deb === 'a' + ? type === 'content' + ? FILE_RELATIVE_PATHS.DE_VIEW_HOME_CONTENT_A + : FILE_RELATIVE_PATHS.DE_VIEW_HOME_META_A + : type === 'content' + ? FILE_RELATIVE_PATHS.DE_VIEW_HOME_CONTENT_B + : FILE_RELATIVE_PATHS.DE_VIEW_HOME_META_B, + }); +} + +export function assertDocumentDetailPageA(resp: CustomFileResponses) { + expect(resp).to.have.length(4); + expect( + resp.map((s) => ({ + type: s.type, + fullName: s.fullName, + filePath: relative(process.cwd(), s.filePath), + })) + ).to.have.deep.members([ + { + type: TYPES.DE.name, + fullName: FULL_NAMES.DE_VIEW_DOCUMENT_DETAIL_A, + filePath: FILE_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_META_A, + }, + { + type: TYPES.DE.name, + fullName: FULL_NAMES.DE_VIEW_DOCUMENT_DETAIL_A, + filePath: FILE_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_CONTENT_A, + }, + { + type: TYPES.DE.name, + fullName: FULL_NAMES.DE_ROUTE_DOCUMENT_DETAIL_A, + filePath: FILE_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_META_A, + }, + { + type: TYPES.DE.name, + fullName: FULL_NAMES.DE_ROUTE_DOCUMENT_DETAIL_A, + filePath: FILE_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_CONTENT_A, + }, + ]); +} + +export async function assertDocumentDetailPageADelete(session: TestSession, shouldBeDeletedInLocal: boolean) { + expect( + await isNameObsolete(session.orgs.get('default').username, TYPES.DE.name, FULL_NAMES.DE_VIEW_DOCUMENT_DETAIL_A) + ).to.be.true; + expect( + await isNameObsolete(session.orgs.get('default').username, TYPES.DE.name, FULL_NAMES.DE_ROUTE_DOCUMENT_DETAIL_A) + ).to.be.true; + + if (shouldBeDeletedInLocal) { + expect(fs.existsSync(join(session.project.dir, DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A))).to.be.false; + expect(fs.existsSync(join(session.project.dir, DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A))).to.be.false; + } +} + +export function assertNoLocalChanges() { + const statusResult = execCmd('force:source:status --local --json', { + ensureExitCode: 0, + }).jsonOutput.result; + expect(statusResult).to.deep.equal([]); +} + +export function createDocumentDetailPageAInLocal(projectDir: string) { + fs.cpSync(STORE.COMPONENTS.DE_VIEW_DOCUMENT_DETAIL, join(projectDir, DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A), { + recursive: true, + }); + + fs.cpSync( + STORE.COMPONENTS.DE_ROUTE_DOCUMENT_DETAIL, + join(projectDir, DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A), + { + recursive: true, + } + ); +} + +export async function deleteDocumentDetailPageAInLocal(projectDir: string) { + await fs.promises.rm(join(projectDir, DIR_RELATIVE_PATHS.DE_VIEW_DOCUMENT_DETAIL_A), { recursive: true }); + await fs.promises.rm(join(projectDir, DIR_RELATIVE_PATHS.DE_ROUTE_DOCUMENT_DETAIL_A), { recursive: true }); +} + +export async function deleteLocalSource(sourceRelativePath: string, projectDir: string) { + // delete and recreate an empty dir + await fs.promises.rm(join(projectDir, sourceRelativePath), { recursive: true }); + await fs.promises.mkdir(join(projectDir, sourceRelativePath)); +} diff --git a/test/nuts/digitalExperienceBundle/project/.eslintignore b/test/nuts/digitalExperienceBundle/project/.eslintignore new file mode 100644 index 000000000..5f7b681a3 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.eslintignore @@ -0,0 +1,16 @@ +**/lwc/**/*.css +**/lwc/**/*.html +**/lwc/**/*.json +**/lwc/**/*.svg +**/lwc/**/*.xml +**/aura/**/*.auradoc +**/aura/**/*.cmp +**/aura/**/*.css +**/aura/**/*.design +**/aura/**/*.evt +**/aura/**/*.json +**/aura/**/*.svg +**/aura/**/*.tokens +**/aura/**/*.xml +**/aura/**/*.app +.sfdx diff --git a/test/nuts/digitalExperienceBundle/project/.forceignore b/test/nuts/digitalExperienceBundle/project/.forceignore new file mode 100755 index 000000000..7b5b5a71f --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.forceignore @@ -0,0 +1,12 @@ +# List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status +# More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm +# + +package.xml + +# LWC configuration files +**/jsconfig.json +**/.eslintrc.json + +# LWC Jest +**/__tests__/** \ No newline at end of file diff --git a/test/nuts/digitalExperienceBundle/project/.gitignore b/test/nuts/digitalExperienceBundle/project/.gitignore new file mode 100644 index 000000000..f5f33ebd8 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.gitignore @@ -0,0 +1,45 @@ +# This file is used for Git repositories to specify intentionally untracked files that Git should ignore. +# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore +# For useful gitignore templates see: https://github.com/github/gitignore + +# Salesforce cache +.sf/ +.sfdx/ +.localdevserver/ +deploy-options.json + +# LWC VSCode autocomplete +**/lwc/jsconfig.json + +# LWC Jest coverage reports +coverage/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Dependency directories +node_modules/ + +# Eslint cache +.eslintcache + +# MacOS system files +.DS_Store + +# Windows system files +Thumbs.db +ehthumbs.db +[Dd]esktop.ini +$RECYCLE.BIN/ + +# Local environment variables +.env + +# Python Salesforce Functions +**/__pycache__/ +**/.venv/ +**/venv/ diff --git a/test/nuts/digitalExperienceBundle/project/.husky/pre-commit b/test/nuts/digitalExperienceBundle/project/.husky/pre-commit new file mode 100755 index 000000000..feac116af --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run precommit \ No newline at end of file diff --git a/test/nuts/digitalExperienceBundle/project/.prettierignore b/test/nuts/digitalExperienceBundle/project/.prettierignore new file mode 100755 index 000000000..f3720b237 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.prettierignore @@ -0,0 +1,10 @@ +# List files or directories below to ignore them when running prettier +# More information: https://prettier.io/docs/en/ignore.html +# + +**/staticresources/** +.localdevserver +.sfdx +.vscode + +coverage/ \ No newline at end of file diff --git a/test/nuts/digitalExperienceBundle/project/.prettierrc b/test/nuts/digitalExperienceBundle/project/.prettierrc new file mode 100755 index 000000000..4f62de2fc --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.prettierrc @@ -0,0 +1,17 @@ +{ + "trailingComma": "none", + "overrides": [ + { + "files": "**/lwc/**/*.html", + "options": { + "parser": "lwc" + } + }, + { + "files": "*.{cmp,page,component}", + "options": { + "parser": "html" + } + } + ] +} diff --git a/test/nuts/digitalExperienceBundle/project/.vscode/extensions.json b/test/nuts/digitalExperienceBundle/project/.vscode/extensions.json new file mode 100644 index 000000000..7e6cb105e --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "salesforce.salesforcedx-vscode", + "redhat.vscode-xml", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "financialforce.lana" + ] +} diff --git a/test/nuts/digitalExperienceBundle/project/.vscode/launch.json b/test/nuts/digitalExperienceBundle/project/.vscode/launch.json new file mode 100644 index 000000000..e07e39173 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Apex Replay Debugger", + "type": "apex-replay", + "request": "launch", + "logFile": "${command:AskForLogFileName}", + "stopOnEntry": true, + "trace": true + } + ] +} diff --git a/test/nuts/digitalExperienceBundle/project/.vscode/settings.json b/test/nuts/digitalExperienceBundle/project/.vscode/settings.json new file mode 100644 index 000000000..76decfbdf --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/.sfdx": true + } +} diff --git a/test/nuts/digitalExperienceBundle/project/README.md b/test/nuts/digitalExperienceBundle/project/README.md new file mode 100644 index 000000000..84ef84cd2 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/README.md @@ -0,0 +1,21 @@ +# Salesforce DX Project: Next Steps + +Now that you’ve created a Salesforce DX project, what’s next? Here are some documentation resources to get you started. + +## How Do You Plan to Deploy Your Changes? + +Do you want to deploy a set of changes, or create a self-contained application? Choose +a [development model](https://developer.salesforce.com/tools/vscode/en/user-guide/development-models). + +## Configure Your Salesforce DX Project + +The `sfdx-project.json` file contains useful configuration information for your project. +See [Salesforce DX Project Configuration](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_config.htm) +in the _Salesforce DX Developer Guide_ for details about this file. + +## Read All About It + +- [Salesforce Extensions Documentation](https://developer.salesforce.com/tools/vscode/) +- [Salesforce CLI Setup Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_intro.htm) +- [Salesforce DX Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro.htm) +- [Salesforce CLI Command Reference](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference.htm) diff --git a/test/nuts/digitalExperienceBundle/project/config/project-scratch-def.json b/test/nuts/digitalExperienceBundle/project/config/project-scratch-def.json new file mode 100644 index 000000000..8d79f2d99 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/config/project-scratch-def.json @@ -0,0 +1,19 @@ +{ + "orgName": "DigitalExperienceBundle NUTs", + "edition": "Developer", + "features": ["EnableSetPasswordInApi", "Communities"], + "settings": { + "lightningExperienceSettings": { + "enableS1DesktopEnabled": true + }, + "mobileSettings": { + "enableS1EncryptedStoragePref2": false + }, + "experienceBundleSettings": { + "enableExperienceBundleMetadata": true + }, + "communitiesSettings": { + "enableNetworksEnabled": true + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls b/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls new file mode 100644 index 000000000..9633c5ac0 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls @@ -0,0 +1,12 @@ +/** + * An apex page controller that takes the user to the right start page based on credentials or lack thereof + */ +public with sharing class CommunitiesLandingController { + + // Code we will invoke on page load. + public PageReference forwardToStartPage() { + return Network.communitiesLanding(); + } + + public CommunitiesLandingController() {} +} \ No newline at end of file diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls-meta.xml new file mode 100644 index 000000000..aacdb59cb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/classes/CommunitiesLandingController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 46.0 + Active + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_A1.digitalExperienceConfig-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_A1.digitalExperienceConfig-meta.xml new file mode 100644 index 000000000..3829bf114 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_A1.digitalExperienceConfig-meta.xml @@ -0,0 +1,8 @@ + + + + + CapricornCoffeeA + + site/Capricorn_Coffee_A1 + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_B1.digitalExperienceConfig-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_B1.digitalExperienceConfig-meta.xml new file mode 100644 index 000000000..ea7e3ddf2 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperienceConfigs/Capricorn_Coffee_B1.digitalExperienceConfig-meta.xml @@ -0,0 +1,8 @@ + + + + + CapricornCoffeeB + + site/Capricorn_Coffee_B1 + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/Capricorn_Coffee_A1.digitalExperience-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/Capricorn_Coffee_A1.digitalExperience-meta.xml new file mode 100644 index 000000000..3223a5aa9 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/Capricorn_Coffee_A1.digitalExperience-meta.xml @@ -0,0 +1,5 @@ + + + meta space a + + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/_meta.json new file mode 100644 index 000000000..9d47ccb15 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "mainAppPage", + "type": "sfdc_cms__appPage", + "path": "" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/content.json new file mode 100644 index 000000000..a6a0c772a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__appPage/mainAppPage/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__appPage", + "title": "main", + "contentBody": { + "currentThemeId": "Build_Your_Own_LWR", + "headMarkup": "\n\nWelcome to LWC Communities!\n\n\n\n\n\n\n\n\n\n\n\n", + "isLockerServiceEnabled": true, + "isRelaxedCSPLevel": false, + "templateName": "talon-template-byo" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json new file mode 100644 index 000000000..622f3c734 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Build_Your_Own_LWR", + "type": "sfdc_cms__brandingSet", + "path": "brandingSets" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json new file mode 100644 index 000000000..e8114fe52 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json @@ -0,0 +1,183 @@ +{ + "type": "sfdc_cms__brandingSet", + "title": "Build Your Own (LWR)", + "contentBody": { + "brandingSetType": "APP", + "definitionName": "talon-template-byo:branding", + "values": { + "BackgroundColor": "#ffffff", + "BaseFontSize": "1rem", + "BodyFont": "Salesforce Sans", + "BodyFontSize": "1rem", + "BodyFontStyle": "normal", + "BodyFontWeight": "400", + "BodyLetterSpacing": "0em", + "BodyLineHeight": "1.5", + "BodySmallFont": "Salesforce Sans", + "BodySmallFontSize": "0.75rem", + "BodySmallFontStyle": "normal", + "BodySmallFontWeight": "400", + "BodySmallLetterSpacing": "0em", + "BodySmallLineHeight": "1.25", + "BodySmallTextColor": "var(--dxp-g-root-contrast)", + "BodySmallTextDecoration": "none", + "BodySmallTextTransform": "none", + "BodyTextColor": "var(--dxp-g-root-contrast)", + "BodyTextDecoration": "none", + "BodyTextTransform": "none", + "ButtonActiveColor": "var(--dxp-s-button-color-1)", + "ButtonBorderRadius": "4px", + "ButtonColor": "var(--dxp-g-brand)", + "ButtonFocusColor": "var(--dxp-s-button-color-1)", + "ButtonFont": "Salesforce Sans", + "ButtonFontSize": "1rem", + "ButtonFontStyle": "normal", + "ButtonFontWeight": "400", + "ButtonHoverColor": "var(--dxp-s-button-color-1)", + "ButtonLargeBorderRadius": "4px", + "ButtonLargeFontSize": "1.25rem", + "ButtonLargePadding": "1.25rem", + "ButtonLetterSpacing": "0em", + "ButtonLineHeight": "2", + "ButtonPadding": "1rem", + "ButtonSmallBorderRadius": "4px", + "ButtonSmallFontSize": "0.75rem", + "ButtonSmallPadding": "0.75rem", + "ButtonTextTransform": "none", + "ColumnSpacerSizeDesktop": "1rem", + "ColumnSpacerSizeMobile": "0.75rem", + "ComponentSpacerSizeDesktop": "1.5rem", + "ComponentSpacerSizeMobile": "1.5rem", + "DropdownBackgroundColor": "var(--dxp-g-root)", + "DropdownBackgroundHoverColor": "var(--dxp-g-neutral)", + "DropdownBorderColor": "var(--dxp-g-neutral)", + "DropdownTextColor": "var(--dxp-g-root-contrast)", + "DropdownTextHoverColor": "var(--dxp-g-neutral-contrast)", + "FormElementBackgroundColor": "var(--dxp-g-root)", + "FormElementBorderColor": "var(--dxp-g-neutral-3)", + "FormElementBorderRadius": "4px", + "FormElementBorderWidth": "1px", + "FormElementLabelColor": "var(--dxp-g-root-contrast)", + "FormElementTextColor": "var(--dxp-g-root-contrast)", + "HeadingExtraLargeColor": "var(--dxp-g-root-contrast)", + "HeadingExtraLargeFont": "Salesforce Sans", + "HeadingExtraLargeFontSize": "2.5rem", + "HeadingExtraLargeFontStyle": "normal", + "HeadingExtraLargeFontWeight": "300", + "HeadingExtraLargeLetterSpacing": "0em", + "HeadingExtraLargeLineHeight": "1.25", + "HeadingExtraLargeTextDecoration": "none", + "HeadingExtraLargeTextTransform": "none", + "HeadingLargeColor": "var(--dxp-g-root-contrast)", + "HeadingLargeFont": "Salesforce Sans", + "HeadingLargeFontSize": "1.75rem", + "HeadingLargeFontStyle": "normal", + "HeadingLargeFontWeight": "300", + "HeadingLargeLetterSpacing": "0em", + "HeadingLargeLineHeight": "1.25", + "HeadingLargeTextDecoration": "none", + "HeadingLargeTextTransform": "none", + "HeadingMediumColor": "var(--dxp-g-root-contrast)", + "HeadingMediumFont": "Salesforce Sans", + "HeadingMediumFontSize": "1.25rem", + "HeadingMediumFontStyle": "normal", + "HeadingMediumFontWeight": "300", + "HeadingMediumLetterSpacing": "0em", + "HeadingMediumLineHeight": "1.25", + "HeadingMediumTextDecoration": "none", + "HeadingMediumTextTransform": "none", + "HeadingSmallColor": "var(--dxp-g-root-contrast)", + "HeadingSmallFont": "Salesforce Sans", + "HeadingSmallFontSize": "1.125rem", + "HeadingSmallFontStyle": "normal", + "HeadingSmallFontWeight": "300", + "HeadingSmallLetterSpacing": "0em", + "HeadingSmallLineHeight": "1.25", + "HeadingSmallTextDecoration": "none", + "HeadingSmallTextTransform": "none", + "HorizontalRowPaddingDesktop": "1rem", + "HorizontalRowPaddingMobile": "0.75rem", + "LinkColor": "var(--dxp-g-brand)", + "LinkHoverColor": "var(--dxp-s-link-text-color-1)", + "LinkTextDecoration": "none", + "LinkTextDecorationFocus": "underline", + "LinkTextDecorationHover": "underline", + "MaxContentWidthDesktop": "1800px", + "MaxContentWidthMobile": "none", + "MobileBaseFontSize": "1rem", + "PrimaryAccentColor": "#005fb2", + "PrimaryAccentForegroundColor": "#ffffff", + "SiteLogo": "", + "TextColor": "#1a1b1e", + "VerticalRowPaddingDesktop": "1rem", + "VerticalRowPaddingMobile": "0.75rem", + "_BackgroundColor1": "#ebebeb", + "_BackgroundColor2": "#c2c2c2", + "_BackgroundColor3": "#858585", + "_ButtonActiveColorContrast": "var(--dxp-g-brand-contrast-1)", + "_ButtonColor1": "var(--dxp-g-brand-1)", + "_ButtonColorContrast": "var(--dxp-g-brand-contrast)", + "_ButtonFocusColorContrast": "var(--dxp-g-brand-contrast-1)", + "_ButtonHoverColorContrast": "var(--dxp-g-brand-contrast-1)", + "_DestructiveColor": "#c23934", + "_DestructiveColor1": "#a2302b", + "_DestructiveColor2": "#611d1a", + "_DestructiveColor3": "#010000", + "_DestructiveForegroundColor": "#ffffff", + "_DestructiveForegroundColor1": "#ffffff", + "_DestructiveForegroundColor2": "#ffffff", + "_DestructiveForegroundColor3": "#ffffff", + "_InfoColor": "#16325c", + "_InfoColor1": "#0e203b", + "_InfoColor2": "#000000", + "_InfoColor3": "#000000", + "_InfoForegroundColor": "#ffffff", + "_InfoForegroundColor1": "#ffffff", + "_InfoForegroundColor2": "#ffffff", + "_InfoForegroundColor3": "#ffffff", + "_LinkColor1": "var(--dxp-g-brand-1)", + "_NeutralColor": "#ecebea", + "_NeutralColor1": "#d9d7d5", + "_NeutralColor2": "#b2aeaa", + "_NeutralColor3": "#76716b", + "_NeutralForegroundColor": "#000000", + "_NeutralForegroundColor1": "#000000", + "_NeutralForegroundColor2": "#000000", + "_NeutralForegroundColor3": "#ffffff", + "_OfflineColor": "#444444", + "_OfflineColor1": "#303030", + "_OfflineColor2": "#070707", + "_OfflineColor3": "#000000", + "_OfflineForegroundColor": "#ffffff", + "_OfflineForegroundColor1": "#ffffff", + "_OfflineForegroundColor2": "#ffffff", + "_OfflineForegroundColor3": "#ffffff", + "_PrimaryAccentColor1": "#004989", + "_PrimaryAccentColor2": "#001e38", + "_PrimaryAccentColor3": "#000000", + "_PrimaryAccentForegroundColor1": "#ffffff", + "_PrimaryAccentForegroundColor2": "#ffffff", + "_PrimaryAccentForegroundColor3": "#ffffff", + "_SiteLogoUrl": "", + "_SuccessColor": "#4bca81", + "_SuccessColor1": "#36b66c", + "_SuccessColor2": "#237747", + "_SuccessColor3": "#07190f", + "_SuccessForegroundColor": "#000000", + "_SuccessForegroundColor1": "#000000", + "_SuccessForegroundColor2": "#ffffff", + "_SuccessForegroundColor3": "#ffffff", + "_TextColor1": "#000000", + "_TextColor2": "#000000", + "_TextColor3": "#000000", + "_WarningColor": "#ffb75d", + "_WarningColor1": "#ffa534", + "_WarningColor2": "#e27d00", + "_WarningColor3": "#673900", + "_WarningForegroundColor": "#000000", + "_WarningForegroundColor1": "#000000", + "_WarningForegroundColor2": "#000000", + "_WarningForegroundColor3": "#ffffff" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/_meta.json new file mode 100644 index 000000000..bbc8af89a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "languages", + "type": "sfdc_cms__languageSettings", + "path": "_settings" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/content.json new file mode 100644 index 000000000..dba6686fb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__languageSettings/languages/content.json @@ -0,0 +1,21 @@ +{ + "type": "sfdc_cms__languageSettings", + "title": "LanguageContent", + "contentBody": { + "defaultLocale": "en_US", + "languages": [ + { + "isActive": true, + "isAuthoringOnly": false, + "label": "English (US)", + "locale": "en_US" + }, + { + "isActive": true, + "isAuthoringOnly": false, + "label": "French", + "locale": "fr" + } + ] + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/_meta.json new file mode 100644 index 000000000..1d23a7501 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Check_Password", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/content.json new file mode 100644 index 000000000..377f9e4fa --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Check_Password/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Check Password", + "contentBody": { + "activeViewId": "checkPasswordResetEmail", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "check-password", + "urlPrefix": "CheckPasswordResetEmail" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/_meta.json new file mode 100644 index 000000000..faa128a16 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Error", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/content.json new file mode 100644 index 000000000..faf29aeac --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Error/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Error", + "contentBody": { + "activeViewId": "error", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "error", + "urlPrefix": "error" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/_meta.json new file mode 100644 index 000000000..982d96bdb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Forgot_Password", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/content.json new file mode 100644 index 000000000..983554686 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Forgot_Password/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Forgot Password", + "contentBody": { + "activeViewId": "forgotPassword", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "forgot-password", + "urlPrefix": "ForgotPassword" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/_meta.json new file mode 100644 index 000000000..0536e9fe1 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Home", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/content.json new file mode 100644 index 000000000..0ebaa84d5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Home/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Home", + "contentBody": { + "activeViewId": "home", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "home", + "urlPrefix": "" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/_meta.json new file mode 100644 index 000000000..38723736a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Login", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/content.json new file mode 100644 index 000000000..87bcfb8f4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Login/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Login", + "contentBody": { + "activeViewId": "login", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "login-main", + "urlPrefix": "login" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/_meta.json new file mode 100644 index 000000000..3de27e7e9 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "News_Detail__c", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/content.json new file mode 100644 index 000000000..be20ca96a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/News_Detail__c/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "News Detail", + "contentBody": { + "activeViewId": "newsDetail", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "managed-content-sfdc_cms__news", + "urlPrefix": "news" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/_meta.json new file mode 100644 index 000000000..5343cfeb5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Register", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/content.json new file mode 100644 index 000000000..e11fc2de6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Register/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Register", + "contentBody": { + "activeViewId": "register", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "self-register", + "urlPrefix": "SelfRegister" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/_meta.json new file mode 100644 index 000000000..c70c814dc --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Service_Not_Available", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/content.json new file mode 100644 index 000000000..38c5b1b02 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Service_Not_Available/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Service Not Available", + "contentBody": { + "activeViewId": "serviceNotAvailable", + "configurationTags": ["allow-in-static-site"], + "pageAccess": "UseParent", + "routeType": "service-not-available", + "urlPrefix": "service-not-available" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/_meta.json new file mode 100644 index 000000000..85e6214a2 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Too_Many_Requests", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/content.json new file mode 100644 index 000000000..21bd056e5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__route/Too_Many_Requests/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Too Many Requests", + "contentBody": { + "activeViewId": "tooManyRequests", + "configurationTags": ["allow-in-static-site", "too-many-requests"], + "pageAccess": "UseParent", + "routeType": "too-many-requests", + "urlPrefix": "too-many-requests" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/_meta.json new file mode 100644 index 000000000..ae7893122 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Capricorn_Coffee_A1", + "type": "sfdc_cms__site", + "path": "" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/content.json new file mode 100644 index 000000000..6bdeea7c1 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__site/Capricorn_Coffee_A1/content.json @@ -0,0 +1,7 @@ +{ + "type": "sfdc_cms__site", + "title": "Capricorn_Coffee_A", + "contentBody": { + "authenticationType": "AUTHENTICATED" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json new file mode 100644 index 000000000..df07f0d33 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Build_Your_Own_LWR", + "type": "sfdc_cms__theme", + "path": "themes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/content.json new file mode 100644 index 000000000..e5bd336f6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__theme/Build_Your_Own_LWR/content.json @@ -0,0 +1,18 @@ +{ + "type": "sfdc_cms__theme", + "title": "Build Your Own (LWR)", + "contentBody": { + "activeBrandingSetId": "Build_Your_Own_LWR", + "definitionName": "byo", + "layouts": [ + { + "layoutId": "snaThemeLayout", + "layoutType": "ServiceNotAvailable" + }, + { + "layoutId": "scopedHeaderAndFooter", + "layoutType": "Inner" + } + ] + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json new file mode 100644 index 000000000..70e9f2c33 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "scopedHeaderAndFooter", + "type": "sfdc_cms__themeLayout", + "path": "themeLayouts" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json new file mode 100644 index 000000000..a43458a4b --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json @@ -0,0 +1,66 @@ +{ + "type": "sfdc_cms__themeLayout", + "title": "Scoped Header and Footer", + "contentBody": { + "component": { + "attributes": {}, + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"7df7d742-a4cc-46ad-a7ba-1d281db40e4f\",\"columns\":[{\"UUID\":\"26e40a92-afb4-4849-9c0e-e269c4e9744e\",\"columnName\":\"Column 1\",\"columnKey\":\"headerSection\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "id": "26e40a92-afb4-4849-9c0e-e269c4e9744e", + "name": "headerSection", + "title": "Theme Header", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "7df7d742-a4cc-46ad-a7ba-1d281db40e4f", + "type": "component" + } + ], + "id": "48c33f30-0793-4049-8955-a294de235406", + "name": "header", + "title": "Theme Header", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"846e74d7-e72c-4314-8482-7e694b4c48ac\",\"columns\":[{\"UUID\":\"a8ff3e9c-5fe7-44e3-a0c9-f5117560771e\",\"columnName\":\"Column 1\",\"columnKey\":\"footerSection\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "id": "a8ff3e9c-5fe7-44e3-a0c9-f5117560771e", + "name": "footerSection", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "846e74d7-e72c-4314-8482-7e694b4c48ac", + "type": "component" + } + ], + "id": "7c33ace7-6b2f-4b39-9533-4dcb633b9a47", + "name": "footer", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_byo:scopedHeaderAndFooter", + "id": "45699225-327c-4ae7-a5a1-b284fac0026b", + "type": "component" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json new file mode 100644 index 000000000..0e29650fe --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "snaThemeLayout", + "type": "sfdc_cms__themeLayout", + "path": "themeLayouts" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/content.json new file mode 100644 index 000000000..300ce6dc4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__themeLayout/snaThemeLayout/content.json @@ -0,0 +1,26 @@ +{ + "type": "sfdc_cms__themeLayout", + "title": "Service Not Available Theme Layout", + "contentBody": { + "component": { + "attributes": {}, + "children": [ + { + "id": "db3f1302-25f8-4ede-b3d4-509ad1f54398", + "name": "header", + "title": "Theme Header", + "type": "region" + }, + { + "id": "9ac188de-55be-46f4-a33a-8a28ee0440cb", + "name": "footer", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_layout:simpleThemeLayout", + "id": "e9947119-ec8f-4fdc-aac8-87cc4f69fd1f", + "type": "component" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/_meta.json new file mode 100644 index 000000000..91b486255 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "checkPasswordResetEmail", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/content.json new file mode 100644 index 000000000..25e1ff5ba --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/checkPasswordResetEmail/content.json @@ -0,0 +1,81 @@ +{ + "type": "sfdc_cms__view", + "title": "Check Password", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"6ec5b6be-f2ad-4b3c-b7ac-51af00aa24a0\",\"columns\":[{\"UUID\":\"ab4b9cfb-e022-4dd2-976c-1cac71a2cfc8\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "ab74ecf8-fa75-4476-924f-deee887770eb", + "type": "component" + }, + { + "attributes": { + "checkEmailMessage": "Check the email account associated with your username for the link to reset your password. If you didn't get an email, check your Spam folder. Or contact your administrator.", + "returnButtonLabel": "Back to login", + "titleLabel": "Now check your email" + }, + "definition": "community_login:checkEmail", + "id": "ace33401-6b9a-415e-b12d-022e7c5e3e86", + "type": "component" + } + ], + "id": "ab4b9cfb-e022-4dd2-976c-1cac71a2cfc8", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "6ec5b6be-f2ad-4b3c-b7ac-51af00aa24a0", + "type": "component" + } + ], + "id": "b8c3ae29-106b-4896-97bf-153bb6572ae0", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Check Password", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "5a4a7fee-6090-472d-983c-a744bb9409dd", + "type": "component" + } + ], + "id": "9596c43a-5434-4ccb-9b51-eb183e280513", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "014d8a0c-d07c-4e22-a31f-28e2a25b51ff", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "check-password" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/_meta.json new file mode 100644 index 000000000..26f2908b0 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "error", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/content.json new file mode 100644 index 000000000..37e0e42e8 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/error/content.json @@ -0,0 +1,70 @@ +{ + "type": "sfdc_cms__view", + "title": "Error", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"f05de15a-eac4-41b4-a73a-697ec108f916\",\"columns\":[{\"UUID\":\"662ed605-89be-459f-8d1e-01094288d08c\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "

Invalid Page

" + }, + "definition": "community_builder:richTextEditor", + "id": "e7f3a31b-0b6a-4180-b7ff-845d692d9e84", + "type": "component" + } + ], + "id": "662ed605-89be-459f-8d1e-01094288d08c", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "f05de15a-eac4-41b4-a73a-697ec108f916", + "type": "component" + } + ], + "id": "ce175332-698f-4ca4-8bb2-739aac5646e7", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Error", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "3feceaf8-0319-4579-8a13-0e744ab06a96", + "type": "component" + } + ], + "id": "574e2e36-c060-4dcb-94f8-c2bc992eebd4", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "c70207fb-b6c0-4d05-b9fb-12e99d50d3e9", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "error" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/_meta.json new file mode 100644 index 000000000..e099f6546 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "forgotPassword", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/content.json new file mode 100644 index 000000000..784fe55e4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/forgotPassword/content.json @@ -0,0 +1,84 @@ +{ + "type": "sfdc_cms__view", + "title": "Forgot Password", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"e8c30a74-1508-4f33-9fa1-028120285680\",\"columns\":[{\"UUID\":\"ddf6e8be-0259-4398-8d69-ed74f551b2fb\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "78f8f575-ae58-4889-a0db-612c3b425851", + "type": "component" + }, + { + "attributes": { + "cancelButtonLabel": "Cancel", + "checkEmailUrl": "./CheckPasswordResetEmail", + "instructionsLabel": "To reset your password, enter your username. We'll send a reset-password link to the email address associated with your account.", + "submitButtonLabel": "Reset", + "titleLabel": "Forgot your password?", + "usernameLabel": "Username" + }, + "definition": "community_login:forgotPassword", + "id": "bb080539-3678-427e-b7a9-db3b941aa8de", + "type": "component" + } + ], + "id": "ddf6e8be-0259-4398-8d69-ed74f551b2fb", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "e8c30a74-1508-4f33-9fa1-028120285680", + "type": "component" + } + ], + "id": "d0117108-7344-4d25-865e-86ea6ecd6008", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Forgot Password", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "f677a733-f430-4639-84a7-e7df0359f495", + "type": "component" + } + ], + "id": "7b707a89-1d43-4bde-8e55-e58059488abb", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "7574328f-d1ef-4ed0-883e-58ca268c064c", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "forgot-password" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/_meta.json new file mode 100644 index 000000000..d37c7f6ed --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "home", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/content.json new file mode 100644 index 000000000..30ee12dbc --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/content.json @@ -0,0 +1,70 @@ +{ + "type": "sfdc_cms__view", + "title": "Home", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"02518436-42fa-491a-a55a-8075d6b4c64a\",\"columns\":[{\"UUID\":\"a3bb7abc-ce21-4a7e-ae07-5e344043d957\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "

Start Building Your Page

Drag and drop a component into the content slots.
" + }, + "definition": "community_builder:htmlEditor", + "id": "b005b455-63b1-4d58-998e-e99f957c889d", + "type": "component" + } + ], + "id": "a3bb7abc-ce21-4a7e-ae07-5e344043d957", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "02518436-42fa-491a-a55a-8075d6b4c64a", + "type": "component" + } + ], + "id": "40697a41-2a32-4c92-a459-92da130357a2", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Home", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "373d9197-59df-4379-a8dd-816bdcd5d90f", + "type": "component" + } + ], + "id": "155a5ede-7a50-4b13-91ee-b7a9f696b7a7", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "689caf33-5b40-425f-9d22-2620e861b918", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "home" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/fr.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/fr.json new file mode 100644 index 000000000..74b4046a6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/home/fr.json @@ -0,0 +1,16 @@ +{ + "type": "sfdc_cms__view", + "title": "Home", + "contentBody": { + "component": { + "children": [ + { + "attributes": { + "richTextValue": "

FR Start Building Your Page

FR Drag and drop a component into the content slots.
" + }, + "id": "b005b455-63b1-4d58-998e-e99f957c889d" + } + ] + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/_meta.json new file mode 100644 index 000000000..eb8f11248 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "login", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/content.json new file mode 100644 index 000000000..4b1552ae4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/login/content.json @@ -0,0 +1,94 @@ +{ + "type": "sfdc_cms__view", + "title": "Login", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"0a6454f9-e305-463f-b312-c596e7a89e00\",\"columns\":[{\"UUID\":\"05bf83cd-7d40-4a65-aca5-b97f676aa691\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "2c0b9780-de4a-4d03-b8f0-ba32dbf3c923", + "type": "component" + }, + { + "attributes": { + "forgotPasswordLabel": "Forgot your password?", + "forgotPasswordUrl": "/ForgotPassword", + "loginButtonLabel": "Log In", + "passwordLabel": "Password", + "selfRegisterLabel": "Not a member?", + "selfRegisterUrl": "/SelfRegister", + "startUrl": "", + "usernameLabel": "Username" + }, + "definition": "community_login:loginForm", + "id": "efd5e0d6-f559-4a65-a2c5-76ce58604c2b", + "type": "component" + }, + { + "attributes": { + "employeeLoginLinkLabel": "Are you an employee? Log in" + }, + "definition": "community_login:employeeLoginLink", + "id": "38af2861-9103-4dd7-b999-6675afe392cc", + "type": "component" + } + ], + "id": "05bf83cd-7d40-4a65-aca5-b97f676aa691", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "0a6454f9-e305-463f-b312-c596e7a89e00", + "type": "component" + } + ], + "id": "ef9f8997-7f01-4bad-8b57-a3c06e6bc294", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Login", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "cb6420b6-9f0d-4b58-94f1-1a49c743d38b", + "type": "component" + } + ], + "id": "5065b9b4-0d25-4a25-986f-de12e3abf197", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "8b55b15f-35ad-4141-8861-52cade23e916", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "login-main" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/_meta.json new file mode 100644 index 000000000..2cb00203a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "newsDetail", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/content.json new file mode 100644 index 000000000..01202b8f7 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/newsDetail/content.json @@ -0,0 +1,60 @@ +{ + "type": "sfdc_cms__view", + "title": "News Detail", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"81efd6b4-a579-43a8-999c-c8a355b387bb\",\"columns\":[{\"UUID\":\"795c9ca5-0aee-42c3-8d76-848b975f1aeb\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":[]}]}" + }, + "children": [ + { + "id": "795c9ca5-0aee-42c3-8d76-848b975f1aeb", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "81efd6b4-a579-43a8-999c-c8a355b387bb", + "type": "component" + } + ], + "id": "acc49e2f-2754-4b19-92d4-144fd2808262", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "{!Content.contentTypeLabel}.{!Content.title}", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "4ba7f27c-4fe0-4099-b259-be80a639bcc3", + "type": "component" + } + ], + "id": "df3c7e5b-794f-4805-bd53-1f55653d1a54", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "3b82df08-1aeb-40c3-a16a-b5129f46f6dd", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "managed-content-sfdc_cms__news" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/_meta.json new file mode 100644 index 000000000..1d207a98b --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "register", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/content.json new file mode 100644 index 000000000..504002198 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/register/content.json @@ -0,0 +1,87 @@ +{ + "type": "sfdc_cms__view", + "title": "Register", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"4aa692b3-19e2-4487-b37f-7d4f4f461649\",\"columns\":[{\"UUID\":\"13cedf7b-4505-4afc-a05a-21f36003f37d\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "9e79fd44-dacf-4ee9-9135-f6ea33d5819f", + "type": "component" + }, + { + "attributes": { + "cancelLinkLabel": "Already have an account?", + "confirmPasswordLabel": "Confirm Password", + "emailLabel": "Email", + "firstnameLabel": "First Name", + "includePasswordField": true, + "lastnameLabel": "Last Name", + "passwordLabel": "Create Password", + "regConfirmUrl": "./CheckPasswordResetEmail", + "submitButtonLabel": "Sign Up" + }, + "definition": "community_login:selfRegister", + "id": "8b0ebad5-73dc-4d3d-9756-1b018ec4ddc7", + "type": "component" + } + ], + "id": "13cedf7b-4505-4afc-a05a-21f36003f37d", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "4aa692b3-19e2-4487-b37f-7d4f4f461649", + "type": "component" + } + ], + "id": "136aab83-63a7-4f76-88ad-58e4c829b1d9", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Register", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "ef577450-4bd2-4364-8452-882159c99e24", + "type": "component" + } + ], + "id": "8f2ac921-3644-41ab-a336-b280d0148553", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "1cd38f26-7c5a-4832-bbe4-27a2e77c89cf", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "self-register" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/_meta.json new file mode 100644 index 000000000..039a745ba --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "serviceNotAvailable", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/content.json new file mode 100644 index 000000000..2c664b86e --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/serviceNotAvailable/content.json @@ -0,0 +1,51 @@ +{ + "type": "sfdc_cms__view", + "title": "Service Not Available", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"6ea2840d-2136-43b4-ab26-9c8156d17560\",\"columns\":[{\"UUID\":\"5f0295c0-aa1d-4115-9ad7-eab68c314157\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "
\n\t
\n
\n
\n\t

Looks like the site is temporarily unavailable

\n\t
\n\t

Please try again in a bit.

\n
" + }, + "definition": "community_builder:htmlEditor", + "id": "4fcbed41-d6ab-4b0c-8589-aab90b2c609c", + "type": "component" + } + ], + "id": "5f0295c0-aa1d-4115-9ad7-eab68c314157", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "6ea2840d-2136-43b4-ab26-9c8156d17560", + "type": "component" + } + ], + "id": "224be488-b95b-44c2-b032-a6c64ce97146", + "name": "content", + "title": "Content", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "71d1c2d4-4ec0-4092-8d31-2a63056a42b2", + "type": "component" + }, + "themeLayoutType": "ServiceNotAvailable", + "viewType": "service-not-available" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/_meta.json new file mode 100644 index 000000000..f9baafc9e --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "tooManyRequests", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/content.json new file mode 100644 index 000000000..731faedcc --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_A1/sfdc_cms__view/tooManyRequests/content.json @@ -0,0 +1,57 @@ +{ + "type": "sfdc_cms__view", + "title": "Too Many Requests", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"a4d450d5-32ff-4842-8b5c-e2b42565890f\",\"columns\":[{\"UUID\":\"dd582521-1e0e-4ce6-ac50-c70eb426e9fd\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "
\n\t
\n
\n
\n\t

Looks like the site is experiencing higher than usual demand…

\n\t

Don't go anywhere. We'll redirect you in a moment.

\n
" + }, + "definition": "community_builder:htmlEditor", + "id": "54f4923d-fc4b-400a-9187-0bd74921c4f2", + "type": "component" + }, + { + "attributes": {}, + "definition": "experience_availability:autoRefresh", + "id": "3d6f56e2-8c40-48ee-8755-a7b967eda757", + "type": "component" + } + ], + "id": "dd582521-1e0e-4ce6-ac50-c70eb426e9fd", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "a4d450d5-32ff-4842-8b5c-e2b42565890f", + "type": "component" + } + ], + "id": "497a6479-d42b-442f-98d3-74646f513708", + "name": "content", + "title": "Content", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "570eb00b-6f7d-4e5d-b2e9-75faf82f2b1c", + "type": "component" + }, + "themeLayoutType": "ServiceNotAvailable", + "viewType": "too-many-requests" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/Capricorn_Coffee_B1.digitalExperience-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/Capricorn_Coffee_B1.digitalExperience-meta.xml new file mode 100644 index 000000000..21de058f8 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/Capricorn_Coffee_B1.digitalExperience-meta.xml @@ -0,0 +1,5 @@ + + + meta space b + + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/_meta.json new file mode 100644 index 000000000..9d47ccb15 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "mainAppPage", + "type": "sfdc_cms__appPage", + "path": "" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/content.json new file mode 100644 index 000000000..a6a0c772a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__appPage/mainAppPage/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__appPage", + "title": "main", + "contentBody": { + "currentThemeId": "Build_Your_Own_LWR", + "headMarkup": "\n\nWelcome to LWC Communities!\n\n\n\n\n\n\n\n\n\n\n\n", + "isLockerServiceEnabled": true, + "isRelaxedCSPLevel": false, + "templateName": "talon-template-byo" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json new file mode 100644 index 000000000..622f3c734 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Build_Your_Own_LWR", + "type": "sfdc_cms__brandingSet", + "path": "brandingSets" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json new file mode 100644 index 000000000..e8114fe52 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__brandingSet/Build_Your_Own_LWR/content.json @@ -0,0 +1,183 @@ +{ + "type": "sfdc_cms__brandingSet", + "title": "Build Your Own (LWR)", + "contentBody": { + "brandingSetType": "APP", + "definitionName": "talon-template-byo:branding", + "values": { + "BackgroundColor": "#ffffff", + "BaseFontSize": "1rem", + "BodyFont": "Salesforce Sans", + "BodyFontSize": "1rem", + "BodyFontStyle": "normal", + "BodyFontWeight": "400", + "BodyLetterSpacing": "0em", + "BodyLineHeight": "1.5", + "BodySmallFont": "Salesforce Sans", + "BodySmallFontSize": "0.75rem", + "BodySmallFontStyle": "normal", + "BodySmallFontWeight": "400", + "BodySmallLetterSpacing": "0em", + "BodySmallLineHeight": "1.25", + "BodySmallTextColor": "var(--dxp-g-root-contrast)", + "BodySmallTextDecoration": "none", + "BodySmallTextTransform": "none", + "BodyTextColor": "var(--dxp-g-root-contrast)", + "BodyTextDecoration": "none", + "BodyTextTransform": "none", + "ButtonActiveColor": "var(--dxp-s-button-color-1)", + "ButtonBorderRadius": "4px", + "ButtonColor": "var(--dxp-g-brand)", + "ButtonFocusColor": "var(--dxp-s-button-color-1)", + "ButtonFont": "Salesforce Sans", + "ButtonFontSize": "1rem", + "ButtonFontStyle": "normal", + "ButtonFontWeight": "400", + "ButtonHoverColor": "var(--dxp-s-button-color-1)", + "ButtonLargeBorderRadius": "4px", + "ButtonLargeFontSize": "1.25rem", + "ButtonLargePadding": "1.25rem", + "ButtonLetterSpacing": "0em", + "ButtonLineHeight": "2", + "ButtonPadding": "1rem", + "ButtonSmallBorderRadius": "4px", + "ButtonSmallFontSize": "0.75rem", + "ButtonSmallPadding": "0.75rem", + "ButtonTextTransform": "none", + "ColumnSpacerSizeDesktop": "1rem", + "ColumnSpacerSizeMobile": "0.75rem", + "ComponentSpacerSizeDesktop": "1.5rem", + "ComponentSpacerSizeMobile": "1.5rem", + "DropdownBackgroundColor": "var(--dxp-g-root)", + "DropdownBackgroundHoverColor": "var(--dxp-g-neutral)", + "DropdownBorderColor": "var(--dxp-g-neutral)", + "DropdownTextColor": "var(--dxp-g-root-contrast)", + "DropdownTextHoverColor": "var(--dxp-g-neutral-contrast)", + "FormElementBackgroundColor": "var(--dxp-g-root)", + "FormElementBorderColor": "var(--dxp-g-neutral-3)", + "FormElementBorderRadius": "4px", + "FormElementBorderWidth": "1px", + "FormElementLabelColor": "var(--dxp-g-root-contrast)", + "FormElementTextColor": "var(--dxp-g-root-contrast)", + "HeadingExtraLargeColor": "var(--dxp-g-root-contrast)", + "HeadingExtraLargeFont": "Salesforce Sans", + "HeadingExtraLargeFontSize": "2.5rem", + "HeadingExtraLargeFontStyle": "normal", + "HeadingExtraLargeFontWeight": "300", + "HeadingExtraLargeLetterSpacing": "0em", + "HeadingExtraLargeLineHeight": "1.25", + "HeadingExtraLargeTextDecoration": "none", + "HeadingExtraLargeTextTransform": "none", + "HeadingLargeColor": "var(--dxp-g-root-contrast)", + "HeadingLargeFont": "Salesforce Sans", + "HeadingLargeFontSize": "1.75rem", + "HeadingLargeFontStyle": "normal", + "HeadingLargeFontWeight": "300", + "HeadingLargeLetterSpacing": "0em", + "HeadingLargeLineHeight": "1.25", + "HeadingLargeTextDecoration": "none", + "HeadingLargeTextTransform": "none", + "HeadingMediumColor": "var(--dxp-g-root-contrast)", + "HeadingMediumFont": "Salesforce Sans", + "HeadingMediumFontSize": "1.25rem", + "HeadingMediumFontStyle": "normal", + "HeadingMediumFontWeight": "300", + "HeadingMediumLetterSpacing": "0em", + "HeadingMediumLineHeight": "1.25", + "HeadingMediumTextDecoration": "none", + "HeadingMediumTextTransform": "none", + "HeadingSmallColor": "var(--dxp-g-root-contrast)", + "HeadingSmallFont": "Salesforce Sans", + "HeadingSmallFontSize": "1.125rem", + "HeadingSmallFontStyle": "normal", + "HeadingSmallFontWeight": "300", + "HeadingSmallLetterSpacing": "0em", + "HeadingSmallLineHeight": "1.25", + "HeadingSmallTextDecoration": "none", + "HeadingSmallTextTransform": "none", + "HorizontalRowPaddingDesktop": "1rem", + "HorizontalRowPaddingMobile": "0.75rem", + "LinkColor": "var(--dxp-g-brand)", + "LinkHoverColor": "var(--dxp-s-link-text-color-1)", + "LinkTextDecoration": "none", + "LinkTextDecorationFocus": "underline", + "LinkTextDecorationHover": "underline", + "MaxContentWidthDesktop": "1800px", + "MaxContentWidthMobile": "none", + "MobileBaseFontSize": "1rem", + "PrimaryAccentColor": "#005fb2", + "PrimaryAccentForegroundColor": "#ffffff", + "SiteLogo": "", + "TextColor": "#1a1b1e", + "VerticalRowPaddingDesktop": "1rem", + "VerticalRowPaddingMobile": "0.75rem", + "_BackgroundColor1": "#ebebeb", + "_BackgroundColor2": "#c2c2c2", + "_BackgroundColor3": "#858585", + "_ButtonActiveColorContrast": "var(--dxp-g-brand-contrast-1)", + "_ButtonColor1": "var(--dxp-g-brand-1)", + "_ButtonColorContrast": "var(--dxp-g-brand-contrast)", + "_ButtonFocusColorContrast": "var(--dxp-g-brand-contrast-1)", + "_ButtonHoverColorContrast": "var(--dxp-g-brand-contrast-1)", + "_DestructiveColor": "#c23934", + "_DestructiveColor1": "#a2302b", + "_DestructiveColor2": "#611d1a", + "_DestructiveColor3": "#010000", + "_DestructiveForegroundColor": "#ffffff", + "_DestructiveForegroundColor1": "#ffffff", + "_DestructiveForegroundColor2": "#ffffff", + "_DestructiveForegroundColor3": "#ffffff", + "_InfoColor": "#16325c", + "_InfoColor1": "#0e203b", + "_InfoColor2": "#000000", + "_InfoColor3": "#000000", + "_InfoForegroundColor": "#ffffff", + "_InfoForegroundColor1": "#ffffff", + "_InfoForegroundColor2": "#ffffff", + "_InfoForegroundColor3": "#ffffff", + "_LinkColor1": "var(--dxp-g-brand-1)", + "_NeutralColor": "#ecebea", + "_NeutralColor1": "#d9d7d5", + "_NeutralColor2": "#b2aeaa", + "_NeutralColor3": "#76716b", + "_NeutralForegroundColor": "#000000", + "_NeutralForegroundColor1": "#000000", + "_NeutralForegroundColor2": "#000000", + "_NeutralForegroundColor3": "#ffffff", + "_OfflineColor": "#444444", + "_OfflineColor1": "#303030", + "_OfflineColor2": "#070707", + "_OfflineColor3": "#000000", + "_OfflineForegroundColor": "#ffffff", + "_OfflineForegroundColor1": "#ffffff", + "_OfflineForegroundColor2": "#ffffff", + "_OfflineForegroundColor3": "#ffffff", + "_PrimaryAccentColor1": "#004989", + "_PrimaryAccentColor2": "#001e38", + "_PrimaryAccentColor3": "#000000", + "_PrimaryAccentForegroundColor1": "#ffffff", + "_PrimaryAccentForegroundColor2": "#ffffff", + "_PrimaryAccentForegroundColor3": "#ffffff", + "_SiteLogoUrl": "", + "_SuccessColor": "#4bca81", + "_SuccessColor1": "#36b66c", + "_SuccessColor2": "#237747", + "_SuccessColor3": "#07190f", + "_SuccessForegroundColor": "#000000", + "_SuccessForegroundColor1": "#000000", + "_SuccessForegroundColor2": "#ffffff", + "_SuccessForegroundColor3": "#ffffff", + "_TextColor1": "#000000", + "_TextColor2": "#000000", + "_TextColor3": "#000000", + "_WarningColor": "#ffb75d", + "_WarningColor1": "#ffa534", + "_WarningColor2": "#e27d00", + "_WarningColor3": "#673900", + "_WarningForegroundColor": "#000000", + "_WarningForegroundColor1": "#000000", + "_WarningForegroundColor2": "#000000", + "_WarningForegroundColor3": "#ffffff" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/_meta.json new file mode 100644 index 000000000..bbc8af89a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "languages", + "type": "sfdc_cms__languageSettings", + "path": "_settings" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/content.json new file mode 100644 index 000000000..dba6686fb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__languageSettings/languages/content.json @@ -0,0 +1,21 @@ +{ + "type": "sfdc_cms__languageSettings", + "title": "LanguageContent", + "contentBody": { + "defaultLocale": "en_US", + "languages": [ + { + "isActive": true, + "isAuthoringOnly": false, + "label": "English (US)", + "locale": "en_US" + }, + { + "isActive": true, + "isAuthoringOnly": false, + "label": "French", + "locale": "fr" + } + ] + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/_meta.json new file mode 100644 index 000000000..1d23a7501 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Check_Password", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/content.json new file mode 100644 index 000000000..377f9e4fa --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Check_Password/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Check Password", + "contentBody": { + "activeViewId": "checkPasswordResetEmail", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "check-password", + "urlPrefix": "CheckPasswordResetEmail" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/_meta.json new file mode 100644 index 000000000..faa128a16 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Error", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/content.json new file mode 100644 index 000000000..faf29aeac --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Error/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Error", + "contentBody": { + "activeViewId": "error", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "error", + "urlPrefix": "error" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/_meta.json new file mode 100644 index 000000000..982d96bdb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Forgot_Password", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/content.json new file mode 100644 index 000000000..983554686 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Forgot_Password/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Forgot Password", + "contentBody": { + "activeViewId": "forgotPassword", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "forgot-password", + "urlPrefix": "ForgotPassword" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/_meta.json new file mode 100644 index 000000000..0536e9fe1 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Home", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/content.json new file mode 100644 index 000000000..0ebaa84d5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Home/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Home", + "contentBody": { + "activeViewId": "home", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "home", + "urlPrefix": "" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/_meta.json new file mode 100644 index 000000000..38723736a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Login", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/content.json new file mode 100644 index 000000000..87bcfb8f4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Login/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Login", + "contentBody": { + "activeViewId": "login", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "login-main", + "urlPrefix": "login" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/_meta.json new file mode 100644 index 000000000..3de27e7e9 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "News_Detail__c", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/content.json new file mode 100644 index 000000000..be20ca96a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/News_Detail__c/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "News Detail", + "contentBody": { + "activeViewId": "newsDetail", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "managed-content-sfdc_cms__news", + "urlPrefix": "news" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/_meta.json new file mode 100644 index 000000000..5343cfeb5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Register", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/content.json new file mode 100644 index 000000000..e11fc2de6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Register/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Register", + "contentBody": { + "activeViewId": "register", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "self-register", + "urlPrefix": "SelfRegister" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/_meta.json new file mode 100644 index 000000000..c70c814dc --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Service_Not_Available", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/content.json new file mode 100644 index 000000000..38c5b1b02 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Service_Not_Available/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Service Not Available", + "contentBody": { + "activeViewId": "serviceNotAvailable", + "configurationTags": ["allow-in-static-site"], + "pageAccess": "UseParent", + "routeType": "service-not-available", + "urlPrefix": "service-not-available" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/_meta.json new file mode 100644 index 000000000..85e6214a2 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Too_Many_Requests", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/content.json new file mode 100644 index 000000000..21bd056e5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__route/Too_Many_Requests/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Too Many Requests", + "contentBody": { + "activeViewId": "tooManyRequests", + "configurationTags": ["allow-in-static-site", "too-many-requests"], + "pageAccess": "UseParent", + "routeType": "too-many-requests", + "urlPrefix": "too-many-requests" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/_meta.json new file mode 100644 index 000000000..ff203e495 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Capricorn_Coffee_B1", + "type": "sfdc_cms__site", + "path": "" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/content.json new file mode 100644 index 000000000..a1c023c87 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__site/Capricorn_Coffee_B1/content.json @@ -0,0 +1,7 @@ +{ + "type": "sfdc_cms__site", + "title": "Capricorn_Coffee_B", + "contentBody": { + "authenticationType": "AUTHENTICATED" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json new file mode 100644 index 000000000..df07f0d33 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Build_Your_Own_LWR", + "type": "sfdc_cms__theme", + "path": "themes" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/content.json new file mode 100644 index 000000000..e5bd336f6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__theme/Build_Your_Own_LWR/content.json @@ -0,0 +1,18 @@ +{ + "type": "sfdc_cms__theme", + "title": "Build Your Own (LWR)", + "contentBody": { + "activeBrandingSetId": "Build_Your_Own_LWR", + "definitionName": "byo", + "layouts": [ + { + "layoutId": "snaThemeLayout", + "layoutType": "ServiceNotAvailable" + }, + { + "layoutId": "scopedHeaderAndFooter", + "layoutType": "Inner" + } + ] + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json new file mode 100644 index 000000000..70e9f2c33 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "scopedHeaderAndFooter", + "type": "sfdc_cms__themeLayout", + "path": "themeLayouts" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json new file mode 100644 index 000000000..7420d388e --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/scopedHeaderAndFooter/content.json @@ -0,0 +1,66 @@ +{ + "type": "sfdc_cms__themeLayout", + "title": "Scoped Header and Footer", + "contentBody": { + "component": { + "attributes": {}, + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"9ca338fc-89b8-4a98-ad6c-f47198dc1194\",\"columns\":[{\"UUID\":\"60ec2cf0-844c-4837-b5ee-6ae7b230e55d\",\"columnName\":\"Column 1\",\"columnKey\":\"headerSection\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "id": "60ec2cf0-844c-4837-b5ee-6ae7b230e55d", + "name": "headerSection", + "title": "Theme Header", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "9ca338fc-89b8-4a98-ad6c-f47198dc1194", + "type": "component" + } + ], + "id": "b1dd1662-5e60-4ff0-bc9e-2bfb45e7d6d7", + "name": "header", + "title": "Theme Header", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"ad98ef7d-8bc3-4aa7-83ba-1287fb5fe777\",\"columns\":[{\"UUID\":\"2a207e21-0dcd-4bcf-933b-e5ccc3f650f8\",\"columnName\":\"Column 1\",\"columnKey\":\"footerSection\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "id": "2a207e21-0dcd-4bcf-933b-e5ccc3f650f8", + "name": "footerSection", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "ad98ef7d-8bc3-4aa7-83ba-1287fb5fe777", + "type": "component" + } + ], + "id": "14e141dd-42a3-4963-b177-6deada3583ae", + "name": "footer", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_byo:scopedHeaderAndFooter", + "id": "d3e616f7-d9d7-4462-8f9d-8796d7d1a807", + "type": "component" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json new file mode 100644 index 000000000..0e29650fe --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "snaThemeLayout", + "type": "sfdc_cms__themeLayout", + "path": "themeLayouts" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/content.json new file mode 100644 index 000000000..45f2966c9 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__themeLayout/snaThemeLayout/content.json @@ -0,0 +1,26 @@ +{ + "type": "sfdc_cms__themeLayout", + "title": "Service Not Available Theme Layout", + "contentBody": { + "component": { + "attributes": {}, + "children": [ + { + "id": "3984581b-abb3-4377-9648-3a268df9b722", + "name": "header", + "title": "Theme Header", + "type": "region" + }, + { + "id": "fb698386-1293-41ac-82e0-80a50dc2ef46", + "name": "footer", + "title": "Theme Footer", + "type": "region" + } + ], + "definition": "community_layout:simpleThemeLayout", + "id": "30720371-91ae-4c81-8c32-3f97800e1137", + "type": "component" + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/_meta.json new file mode 100644 index 000000000..91b486255 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "checkPasswordResetEmail", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/content.json new file mode 100644 index 000000000..88e874b56 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/checkPasswordResetEmail/content.json @@ -0,0 +1,81 @@ +{ + "type": "sfdc_cms__view", + "title": "Check Password", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"91fbb17b-88f5-4689-80f3-c07ea17c00eb\",\"columns\":[{\"UUID\":\"6d64c709-5471-4565-b89e-3559df15d85e\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "2c901a14-9af7-4d40-bffe-b45adc63b864", + "type": "component" + }, + { + "attributes": { + "checkEmailMessage": "Check the email account associated with your username for the link to reset your password. If you didn't get an email, check your Spam folder. Or contact your administrator.", + "returnButtonLabel": "Back to login", + "titleLabel": "Now check your email" + }, + "definition": "community_login:checkEmail", + "id": "36b82640-9dde-482b-9e0d-046aafda9bd8", + "type": "component" + } + ], + "id": "6d64c709-5471-4565-b89e-3559df15d85e", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "91fbb17b-88f5-4689-80f3-c07ea17c00eb", + "type": "component" + } + ], + "id": "004e5a06-67bb-40aa-bdc7-6f4a6a41b9ff", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Check Password", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "735711df-bf5b-41ca-ba8e-fc2a1477c35d", + "type": "component" + } + ], + "id": "d8b062a8-de4a-4410-b6b8-f9252fc8d1d5", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "d0ecaf0b-bf3f-44d5-9300-d13df0ddfc8d", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "check-password" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/_meta.json new file mode 100644 index 000000000..26f2908b0 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "error", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/content.json new file mode 100644 index 000000000..39701ca5b --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/error/content.json @@ -0,0 +1,70 @@ +{ + "type": "sfdc_cms__view", + "title": "Error", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"0191b41d-425c-4d39-b0d4-cfb9d7e8e5a7\",\"columns\":[{\"UUID\":\"a95c67ad-9c45-417d-979d-c3a0806d0089\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "

Invalid Page

" + }, + "definition": "community_builder:richTextEditor", + "id": "849c142c-f57d-4ef1-979a-91b937bad071", + "type": "component" + } + ], + "id": "a95c67ad-9c45-417d-979d-c3a0806d0089", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "0191b41d-425c-4d39-b0d4-cfb9d7e8e5a7", + "type": "component" + } + ], + "id": "5f319b16-ee42-4478-b15b-7cf93c3f2e58", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Error", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "dcbdd984-7f2f-4e29-9af2-dee12b5658f5", + "type": "component" + } + ], + "id": "b76b9173-ce30-46cf-a184-7eae49897804", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "39338038-a7bb-4348-be0c-dd4eed8c1d13", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "error" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/_meta.json new file mode 100644 index 000000000..e099f6546 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "forgotPassword", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/content.json new file mode 100644 index 000000000..070c28369 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/forgotPassword/content.json @@ -0,0 +1,84 @@ +{ + "type": "sfdc_cms__view", + "title": "Forgot Password", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"bac6a759-3569-435a-acec-9d3d8d59f1ad\",\"columns\":[{\"UUID\":\"08a282cb-f55b-4f7a-850a-0303bcca42f6\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "37afe350-297a-41d9-9f05-90fe1d817efd", + "type": "component" + }, + { + "attributes": { + "cancelButtonLabel": "Cancel", + "checkEmailUrl": "./CheckPasswordResetEmail", + "instructionsLabel": "To reset your password, enter your username. We'll send a reset-password link to the email address associated with your account.", + "submitButtonLabel": "Reset", + "titleLabel": "Forgot your password?", + "usernameLabel": "Username" + }, + "definition": "community_login:forgotPassword", + "id": "27df0c0c-3c18-46d5-978a-a479cf17a033", + "type": "component" + } + ], + "id": "08a282cb-f55b-4f7a-850a-0303bcca42f6", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "bac6a759-3569-435a-acec-9d3d8d59f1ad", + "type": "component" + } + ], + "id": "414b93ff-9275-4901-8cfd-1db36879821f", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Forgot Password", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "1b78d478-7c44-452d-80ae-8327684dab69", + "type": "component" + } + ], + "id": "5f7364ca-c1f4-4b7d-97ef-9371c565e1df", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "4e4bcc4e-eb57-4372-a5bf-2af8037bb9e4", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "forgot-password" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/_meta.json new file mode 100644 index 000000000..d37c7f6ed --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "home", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/content.json new file mode 100644 index 000000000..7f45ff80c --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/content.json @@ -0,0 +1,70 @@ +{ + "type": "sfdc_cms__view", + "title": "Home", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"da5b3458-85a9-431d-a2ac-ab37ce5ad6bb\",\"columns\":[{\"UUID\":\"0d102095-1797-4301-a6f5-ac3e9784ea9b\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "

Start Building Your Page

Drag and drop a component into the content slots.
" + }, + "definition": "community_builder:htmlEditor", + "id": "f9e6e7d5-355d-41f3-871b-0a4ff2707699", + "type": "component" + } + ], + "id": "0d102095-1797-4301-a6f5-ac3e9784ea9b", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "da5b3458-85a9-431d-a2ac-ab37ce5ad6bb", + "type": "component" + } + ], + "id": "a2fecd03-f900-457d-b65f-fb6b94b49d44", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Home", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "42f2a5b9-800a-4a39-ba29-364f71dd6637", + "type": "component" + } + ], + "id": "9fdb6916-aaf3-4392-bbe6-00b129b09cbc", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "b32df5b9-2879-49a9-8217-a90aec747323", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "home" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/fr.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/fr.json new file mode 100644 index 000000000..65a176d19 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/home/fr.json @@ -0,0 +1,16 @@ +{ + "type": "sfdc_cms__view", + "title": "Home", + "contentBody": { + "component": { + "children": [ + { + "attributes": { + "richTextValue": "

FR Start Building Your Page

FR Drag and drop a component into the content slots.
" + }, + "id": "f9e6e7d5-355d-41f3-871b-0a4ff2707699" + } + ] + } + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/_meta.json new file mode 100644 index 000000000..eb8f11248 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "login", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/content.json new file mode 100644 index 000000000..8596ffd25 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/login/content.json @@ -0,0 +1,94 @@ +{ + "type": "sfdc_cms__view", + "title": "Login", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"ff1e74c2-6c75-4baa-93e0-1737c7723f34\",\"columns\":[{\"UUID\":\"6a88ec53-8c1e-47b7-badd-d341f7102800\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "bc261efd-d80f-4ab4-8a1f-088dad72e9c8", + "type": "component" + }, + { + "attributes": { + "forgotPasswordLabel": "Forgot your password?", + "forgotPasswordUrl": "/ForgotPassword", + "loginButtonLabel": "Log In", + "passwordLabel": "Password", + "selfRegisterLabel": "Not a member?", + "selfRegisterUrl": "/SelfRegister", + "startUrl": "", + "usernameLabel": "Username" + }, + "definition": "community_login:loginForm", + "id": "03429afd-9d90-43ab-9861-c8db6492f972", + "type": "component" + }, + { + "attributes": { + "employeeLoginLinkLabel": "Are you an employee? Log in" + }, + "definition": "community_login:employeeLoginLink", + "id": "c1225537-04fc-4d2f-9bf3-f6626d9a372d", + "type": "component" + } + ], + "id": "6a88ec53-8c1e-47b7-badd-d341f7102800", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "ff1e74c2-6c75-4baa-93e0-1737c7723f34", + "type": "component" + } + ], + "id": "334e0f57-9b96-4031-9360-429d02a7b435", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Login", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "ce6f5f3a-f393-4d25-9af0-a5f94d60755e", + "type": "component" + } + ], + "id": "33c266f4-a02c-438f-9150-bcc53379a2ba", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "51874150-5951-4e02-a1a4-292bae674440", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "login-main" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/_meta.json new file mode 100644 index 000000000..2cb00203a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "newsDetail", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/content.json new file mode 100644 index 000000000..9fed3db69 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/newsDetail/content.json @@ -0,0 +1,60 @@ +{ + "type": "sfdc_cms__view", + "title": "News Detail", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"c593ae9d-e494-4207-8e91-103e4ea046f4\",\"columns\":[{\"UUID\":\"14e31a64-4ad0-46ed-b215-7d6a7f9db686\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":[]}]}" + }, + "children": [ + { + "id": "14e31a64-4ad0-46ed-b215-7d6a7f9db686", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "c593ae9d-e494-4207-8e91-103e4ea046f4", + "type": "component" + } + ], + "id": "06859da3-16e8-4926-b4ae-980130906196", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "{!Content.contentTypeLabel}.{!Content.title}", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "a6dc2fb9-cef9-4ed8-8269-173122d6faf1", + "type": "component" + } + ], + "id": "2dacca0d-9607-4813-b09a-2f6e27c2c5af", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "c5ad0eb2-74a2-425f-8096-fae05ee7cca9", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "managed-content-sfdc_cms__news" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/_meta.json new file mode 100644 index 000000000..1d207a98b --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "register", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/content.json new file mode 100644 index 000000000..b9ee08b7d --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/register/content.json @@ -0,0 +1,87 @@ +{ + "type": "sfdc_cms__view", + "title": "Register", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"43864ad3-151c-48f5-bc4d-c9fac3479f84\",\"columns\":[{\"UUID\":\"d69310d1-413f-43d0-a107-2dffbcdf0f4d\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "imageInfo": "", + "logoWidth": 250 + }, + "definition": "dxp_content_layout:siteLogo", + "id": "723f9a6f-ce8f-416d-afa0-2d22a9285c39", + "type": "component" + }, + { + "attributes": { + "cancelLinkLabel": "Already have an account?", + "confirmPasswordLabel": "Confirm Password", + "emailLabel": "Email", + "firstnameLabel": "First Name", + "includePasswordField": true, + "lastnameLabel": "Last Name", + "passwordLabel": "Create Password", + "regConfirmUrl": "./CheckPasswordResetEmail", + "submitButtonLabel": "Sign Up" + }, + "definition": "community_login:selfRegister", + "id": "fa84ab4d-d31b-4b0b-8ba4-9a377b33af8c", + "type": "component" + } + ], + "id": "d69310d1-413f-43d0-a107-2dffbcdf0f4d", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "43864ad3-151c-48f5-bc4d-c9fac3479f84", + "type": "component" + } + ], + "id": "30378b5e-9116-491d-bcb9-1d8045be810a", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "Register", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "77b0db41-1c20-426b-8ce0-f8b2e667cf1b", + "type": "component" + } + ], + "id": "0ca965f7-cf0d-42c6-acc2-5692a64d72d5", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "54d1ba23-97d3-404a-bd4d-96b41578f2cc", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "self-register" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/_meta.json new file mode 100644 index 000000000..039a745ba --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "serviceNotAvailable", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/content.json new file mode 100644 index 000000000..2559c522a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/serviceNotAvailable/content.json @@ -0,0 +1,51 @@ +{ + "type": "sfdc_cms__view", + "title": "Service Not Available", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"d08242cd-633d-427a-a73c-c03f588f4b0c\",\"columns\":[{\"UUID\":\"22c00236-cf25-418b-841f-a343803053fc\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "
\n\t
\n
\n
\n\t

Looks like the site is temporarily unavailable

\n\t
\n\t

Please try again in a bit.

\n
" + }, + "definition": "community_builder:htmlEditor", + "id": "f28ebd40-98ce-4e7d-92e6-71dfa572ec57", + "type": "component" + } + ], + "id": "22c00236-cf25-418b-841f-a343803053fc", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "d08242cd-633d-427a-a73c-c03f588f4b0c", + "type": "component" + } + ], + "id": "cc4868d4-5d3b-4329-8c10-8895ac12ccaf", + "name": "content", + "title": "Content", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "bd1dbd62-890f-4fae-913c-1521dea3b04a", + "type": "component" + }, + "themeLayoutType": "ServiceNotAvailable", + "viewType": "service-not-available" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/_meta.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/_meta.json new file mode 100644 index 000000000..f9baafc9e --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "tooManyRequests", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/content.json b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/content.json new file mode 100644 index 000000000..ccf4ffb6f --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/digitalExperiences/site/Capricorn_Coffee_B1/sfdc_cms__view/tooManyRequests/content.json @@ -0,0 +1,57 @@ +{ + "type": "sfdc_cms__view", + "title": "Too Many Requests", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"c2516925-2db5-4d0c-87bb-2ee3359ad4a0\",\"columns\":[{\"UUID\":\"5f83a1a4-43b4-4b2d-af78-bf405942d47b\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":null}]}" + }, + "children": [ + { + "children": [ + { + "attributes": { + "richTextValue": "
\n\t
\n
\n
\n\t

Looks like the site is experiencing higher than usual demand…

\n\t

Don't go anywhere. We'll redirect you in a moment.

\n
" + }, + "definition": "community_builder:htmlEditor", + "id": "dc792e7d-c9c4-49bd-a186-8fa25f39f133", + "type": "component" + }, + { + "attributes": {}, + "definition": "experience_availability:autoRefresh", + "id": "e77d1f07-8f7c-4825-ae32-39d02ce4eb9c", + "type": "component" + } + ], + "id": "5f83a1a4-43b4-4b2d-af78-bf405942d47b", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "c2516925-2db5-4d0c-87bb-2ee3359ad4a0", + "type": "component" + } + ], + "id": "6a87e9eb-80e2-4985-a279-ebb22f3de803", + "name": "content", + "title": "Content", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "71367236-eef9-4c36-b93e-d8aa13cde8cb", + "type": "component" + }, + "themeLayoutType": "ServiceNotAvailable", + "viewType": "too-many-requests" + } +} diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_A.network-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_A.network-meta.xml new file mode 100644 index 000000000..2df0dacde --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_A.network-meta.xml @@ -0,0 +1,55 @@ + + + false + false + unfiled$public/CommunityChangePasswordEmailTemplate + + true + santhosh.e@salesforce.com + Capricorn_Coffee_A + true + false + true + true + false + false + false + false + false + false + false + true + false + false + false + true + true + true + false + false + unfiled$public/CommunityForgotPasswordEmailTemplate + false + unfiled$public/CommunityHeadlessForgotPasswordTemplate + + admin + + + Standard + Designer + Designer + Designer + Designer + + Capricorn_Coffee_A1 + false + true + Capricorn_Coffee_A + NotArchived + UnderConstruction + + home + Chatter + + CapricornCoffeeAvforcesite + unfiled$public/CommunityWelcomeEmailTemplate + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_B.network-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_B.network-meta.xml new file mode 100644 index 000000000..24882dee9 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/networks/Capricorn_Coffee_B.network-meta.xml @@ -0,0 +1,55 @@ + + + false + false + unfiled$public/CommunityChangePasswordEmailTemplate + + true + santhosh.e@salesforce.com + Capricorn_Coffee_B + true + false + true + true + false + false + false + false + false + false + false + true + false + false + false + true + true + true + false + false + unfiled$public/CommunityForgotPasswordEmailTemplate + false + unfiled$public/CommunityHeadlessForgotPasswordTemplate + + admin + + + Standard + Designer + Designer + Designer + Designer + + Capricorn_Coffee_B1 + false + true + Capricorn_Coffee_B + NotArchived + UnderConstruction + + home + Chatter + + CapricornCoffeeBvforcesite + unfiled$public/CommunityWelcomeEmailTemplate + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page b/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page new file mode 100644 index 000000000..8a168e453 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page @@ -0,0 +1,7 @@ + + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page-meta.xml new file mode 100644 index 000000000..c984b0662 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/pages/CommunitiesLanding.page-meta.xml @@ -0,0 +1,8 @@ + + + 46.0 + false + false + Default communities landing page + + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_A.site-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_A.site-meta.xml new file mode 100644 index 000000000..01a3b65ad --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_A.site-meta.xml @@ -0,0 +1,28 @@ + + + true + false + false + false + false + false + true + false + CommunitiesLogin + BandwidthExceeded + true + true + SameOriginOnly + true + true + FileNotFound + Exception + InMaintenance + CommunitiesLanding + Capricorn_Coffee_A + false + true + CommunitiesSelfReg + ChatterNetwork + CapricornCoffeeAvforcesite + diff --git a/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_B.site-meta.xml b/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_B.site-meta.xml new file mode 100644 index 000000000..ec6f2d73c --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/force-app/main/default/sites/Capricorn_Coffee_B.site-meta.xml @@ -0,0 +1,28 @@ + + + true + false + false + false + false + false + true + false + CommunitiesLogin + BandwidthExceeded + true + true + SameOriginOnly + true + true + FileNotFound + Exception + InMaintenance + CommunitiesLanding + Capricorn_Coffee_B + false + true + CommunitiesSelfReg + ChatterNetwork + CapricornCoffeeBvforcesite + diff --git a/test/nuts/digitalExperienceBundle/project/jest.config.js b/test/nuts/digitalExperienceBundle/project/jest.config.js new file mode 100644 index 000000000..410b3d554 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/jest.config.js @@ -0,0 +1,6 @@ +const { jestConfig } = require("@salesforce/sfdx-lwc-jest/config"); + +module.exports = { + ...jestConfig, + modulePathIgnorePatterns: ["/.localdevserver"] +}; diff --git a/test/nuts/digitalExperienceBundle/project/package.json b/test/nuts/digitalExperienceBundle/project/package.json new file mode 100644 index 000000000..4b6163291 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/package.json @@ -0,0 +1,41 @@ +{ + "name": "salesforce-app", + "private": true, + "version": "1.0.0", + "description": "Salesforce App", + "scripts": { + "lint": "eslint **/{aura,lwc}/**", + "test": "npm run test:unit", + "test:unit": "sfdx-lwc-jest", + "test:unit:watch": "sfdx-lwc-jest --watch", + "test:unit:debug": "sfdx-lwc-jest --debug", + "test:unit:coverage": "sfdx-lwc-jest --coverage", + "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "postinstall": "husky install", + "precommit": "lint-staged" + }, + "devDependencies": { + "@lwc/eslint-plugin-lwc": "^1.1.2", + "@prettier/plugin-xml": "^2.0.1", + "@salesforce/eslint-config-lwc": "^3.2.3", + "@salesforce/eslint-plugin-aura": "^2.0.0", + "@salesforce/eslint-plugin-lightning": "^1.0.0", + "@salesforce/sfdx-lwc-jest": "^1.1.0", + "eslint": "^8.11.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.2", + "husky": "^7.0.4", + "lint-staged": "^12.3.7", + "prettier": "^2.6.0", + "prettier-plugin-apex": "^1.10.0" + }, + "lint-staged": { + "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ + "prettier --write" + ], + "**/{aura,lwc}/**": [ + "eslint" + ] + } +} diff --git a/test/nuts/digitalExperienceBundle/project/scripts/apex/hello.apex b/test/nuts/digitalExperienceBundle/project/scripts/apex/hello.apex new file mode 100644 index 000000000..1fba73250 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/scripts/apex/hello.apex @@ -0,0 +1,10 @@ +// Use .apex files to store anonymous Apex. +// You can execute anonymous Apex in VS Code by selecting the +// apex text and running the command: +// SFDX: Execute Anonymous Apex with Currently Selected Text +// You can also execute the entire file by running the command: +// SFDX: Execute Anonymous Apex with Editor Contents + +string tempvar = 'Enter_your_name_here'; +System.debug('Hello World!'); +System.debug('My name is ' + tempvar); \ No newline at end of file diff --git a/test/nuts/digitalExperienceBundle/project/scripts/soql/account.soql b/test/nuts/digitalExperienceBundle/project/scripts/soql/account.soql new file mode 100644 index 000000000..10d4b9c78 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/scripts/soql/account.soql @@ -0,0 +1,6 @@ +// Use .soql files to store SOQL queries. +// You can execute queries in VS Code by selecting the +// query text and running the command: +// SFDX: Execute SOQL Query with Currently Selected Text + +SELECT Id, Name FROM Account diff --git a/test/nuts/digitalExperienceBundle/project/sfdx-project.json b/test/nuts/digitalExperienceBundle/project/sfdx-project.json new file mode 100644 index 000000000..6c1f41836 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/project/sfdx-project.json @@ -0,0 +1,12 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "name": "digitalExperienceBundleProject", + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "57.0" +} diff --git a/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/_meta.json b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/_meta.json new file mode 100644 index 000000000..d79d868fb --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "Document_Detail__c", + "type": "sfdc_cms__route", + "path": "routes" +} diff --git a/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/content.json b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/content.json new file mode 100644 index 000000000..07db9961f --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__route/Document_Detail__c/content.json @@ -0,0 +1,11 @@ +{ + "type": "sfdc_cms__route", + "title": "Document Detail", + "contentBody": { + "activeViewId": "documentDetail", + "configurationTags": [], + "pageAccess": "UseParent", + "routeType": "managed-content-sfdc_cms__document", + "urlPrefix": "document" + } +} diff --git a/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/_meta.json b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/_meta.json new file mode 100644 index 000000000..53d0a748a --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/_meta.json @@ -0,0 +1,5 @@ +{ + "apiName": "documentDetail", + "type": "sfdc_cms__view", + "path": "views" +} diff --git a/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/content.json b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/content.json new file mode 100644 index 000000000..237c6082f --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/components/sfdc_cms__view/documentDetail/content.json @@ -0,0 +1,60 @@ +{ + "type": "sfdc_cms__view", + "title": "Document Detail", + "contentBody": { + "component": { + "children": [ + { + "children": [ + { + "attributes": { + "backgroundImageConfig": "", + "backgroundImageOverlay": "rgba(0,0,0,0)", + "sectionConfig": "{\"UUID\":\"17eac07d-ff48-4480-82f2-6a9288c5f900\",\"columns\":[{\"UUID\":\"1abcbff2-671f-4557-90ee-ea7d653e0166\",\"columnName\":\"Column 1\",\"columnKey\":\"col1\",\"columnWidth\":\"12\",\"seedComponents\":[]}]}" + }, + "children": [ + { + "id": "1abcbff2-671f-4557-90ee-ea7d653e0166", + "name": "col1", + "title": "Column 1", + "type": "region" + } + ], + "definition": "community_layout:section", + "id": "17eac07d-ff48-4480-82f2-6a9288c5f900", + "type": "component" + } + ], + "id": "2be13a58-b7be-49c4-be61-7449cd54b154", + "name": "content", + "title": "Content", + "type": "region" + }, + { + "children": [ + { + "attributes": { + "customHeadTags": "", + "description": "", + "pageTitle": "{!Content.contentTypeLabel}.{!Content.title}", + "recordId": "{!recordId}" + }, + "definition": "community_builder:seoAssistant", + "id": "23caf5c2-87ad-4d99-b5aa-7ec9da9da8d9", + "type": "component" + } + ], + "id": "c47d644b-9e1b-4dfb-afc9-873bc935d953", + "name": "sfdcHiddenRegion", + "title": "sfdcHiddenRegion", + "type": "region" + } + ], + "definition": "community_layout:sldsFlexibleLayout", + "id": "078ff49d-a524-43c5-9fa4-fa78ae6849e6", + "type": "component" + }, + "themeLayoutType": "Inner", + "viewType": "managed-content-sfdc_cms__document" + } +} diff --git a/test/nuts/digitalExperienceBundle/store/manifests/all-de-of-deb-a-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/all-de-of-deb-a-package.xml new file mode 100644 index 000000000..2979172c0 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/all-de-of-deb-a-package.xml @@ -0,0 +1,8 @@ + + + + site/Capricorn_Coffee_A1.* + DigitalExperience + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/all-de-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/all-de-package.xml new file mode 100644 index 000000000..3c55c86c6 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/all-de-package.xml @@ -0,0 +1,8 @@ + + + + * + DigitalExperience + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/all-debs-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/all-debs-package.xml new file mode 100644 index 000000000..bfee651a0 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/all-debs-package.xml @@ -0,0 +1,8 @@ + + + + * + DigitalExperienceBundle + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/de-document-detail-page-a-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/de-document-detail-page-a-package.xml new file mode 100644 index 000000000..a73c6a13f --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/de-document-detail-page-a-package.xml @@ -0,0 +1,9 @@ + + + + site/Capricorn_Coffee_A1.sfdc_cms__view/documentDetail + site/Capricorn_Coffee_A1.sfdc_cms__route/Document_Detail__c + DigitalExperience + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/de-view-home-of-deb-a-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/de-view-home-of-deb-a-package.xml new file mode 100644 index 000000000..bfcca1ff2 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/de-view-home-of-deb-a-package.xml @@ -0,0 +1,8 @@ + + + + site/Capricorn_Coffee_A1.sfdc_cms__view/home + DigitalExperience + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/empty-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/empty-package.xml new file mode 100644 index 000000000..8500306d4 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/empty-package.xml @@ -0,0 +1,4 @@ + + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/full-site-deb-a-and-b-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/full-site-deb-a-and-b-package.xml new file mode 100644 index 000000000..247d4a6b5 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/full-site-deb-a-and-b-package.xml @@ -0,0 +1,24 @@ + + + + site/Capricorn_Coffee_A1 + site/Capricorn_Coffee_B1 + DigitalExperienceBundle + + + Capricorn_Coffee_A1 + Capricorn_Coffee_B1 + DigitalExperienceConfig + + + Capricorn_Coffee_A + Capricorn_Coffee_B + CustomSite + + + Capricorn_Coffee_A + Capricorn_Coffee_B + Network + + 57.0 + diff --git a/test/nuts/digitalExperienceBundle/store/manifests/just-deb-a-package.xml b/test/nuts/digitalExperienceBundle/store/manifests/just-deb-a-package.xml new file mode 100644 index 000000000..dc7631e52 --- /dev/null +++ b/test/nuts/digitalExperienceBundle/store/manifests/just-deb-a-package.xml @@ -0,0 +1,8 @@ + + + + site/Capricorn_Coffee_A1 + DigitalExperienceBundle + + 57.0 + diff --git a/test/nuts/folderTypes.nut.ts b/test/nuts/folderTypes.nut.ts index fea8f038b..dbff0d965 100644 --- a/test/nuts/folderTypes.nut.ts +++ b/test/nuts/folderTypes.nut.ts @@ -11,6 +11,7 @@ import { expect } from 'chai'; import { FileResponse } from '@salesforce/source-deploy-retrieve'; import { DeployCommandResult } from '../../src/formatters/deployResultFormatter'; import { RetrieveCommandResult } from '../../src/formatters/retrieveResultFormatter'; +import { cliForManifestCreate } from './shared/cliForManifestCreate'; describe('metadata types that go in folders', () => { let session: TestSession; @@ -75,7 +76,8 @@ describe('metadata types that go in folders', () => { }, ]; - const getRelativeFileResponses = (resp: FileResponse[]) => resp.map((s) => { + const getRelativeFileResponses = (resp: FileResponse[]) => + resp.map((s) => { // grab the last 2 directories with the file only s.filePath = s.filePath.split(path.sep).slice(-3).join(path.sep); return s; @@ -83,7 +85,10 @@ describe('metadata types that go in folders', () => { it('can generate manifest for just the emailTemplates', () => { const pathToEmails = path.join('force-app', 'main', 'default', 'email'); - execCmd(`force:source:manifest:create -p ${pathToEmails} --json`, { ensureExitCode: 0 }); + execCmd(`force:source:manifest:create -p ${pathToEmails} --json`, { + ensureExitCode: 0, + cli: cliForManifestCreate, + }); expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.true; }); @@ -110,7 +115,10 @@ describe('metadata types that go in folders', () => { it('can generate manifest for just the reports', () => { expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.false; const pathToReports = path.join('force-app', 'main', 'default', 'reports'); - execCmd(`force:source:manifest:create -p ${pathToReports} --json`, { ensureExitCode: 0 }); + execCmd(`force:source:manifest:create -p ${pathToReports} --json`, { + ensureExitCode: 0, + cli: cliForManifestCreate, + }); expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.true; }); diff --git a/test/nuts/ignored_list.nut.ts b/test/nuts/ignored_list.nut.ts deleted file mode 100644 index a8e5a45f8..000000000 --- a/test/nuts/ignored_list.nut.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; -import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; -import { expect } from 'chai'; -import { SourceIgnoredResults } from '../../src/commands/force/source/ignored/list'; - -describe('force:source:ignored:list', () => { - let session: TestSession; - let forceIgnorePath: string; - let originalForceIgnore: string; - - const pathToIgnoredFile1 = path.join('foo-bar', 'app', 'classes', 'FooBar.cls'); - const pathToIgnoredFile2 = path.join('foo-bar', 'app', 'classes', 'FooBar.cls-meta.xml'); - - before(async () => { - session = await TestSession.create({ - project: { - gitClone: 'https://github.com/salesforcecli/sample-project-multiple-packages', - }, - }); - forceIgnorePath = path.join(session.project.dir, '.forceignore'); - originalForceIgnore = await fs.promises.readFile(forceIgnorePath, 'utf8'); - }); - - after(async () => { - await session?.clean(); - }); - - describe('no forceignore', () => { - before(async () => { - await fs.promises.rm(forceIgnorePath); - }); - after(async () => { - await fs.promises.writeFile(forceIgnorePath, originalForceIgnore); - }); - it('default PkgDir', () => { - const result = execCmd('force:source:ignored:list --json', { ensureExitCode: 0 }).jsonOutput - .result; - expect(result.ignoredFiles).to.deep.equal([]); - }); - it('specified sourcePath', () => { - const result2 = execCmd('force:source:ignored:list --json -p foo-bar', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result2.ignoredFiles).to.deep.equal([]); - }); - }); - - describe('no files are ignored (empty forceignore)', () => { - before(async () => { - await fs.promises.writeFile(forceIgnorePath, ''); - }); - after(async () => { - await fs.promises.writeFile(forceIgnorePath, originalForceIgnore); - }); - it('default PkgDir', () => { - const result = execCmd('force:source:ignored:list --json', { ensureExitCode: 0 }).jsonOutput - .result; - expect(result.ignoredFiles).to.deep.equal([]); - }); - it('specified sourcePath', () => { - const result2 = execCmd('force:source:ignored:list --json -p foo-bar', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result2.ignoredFiles).to.deep.equal([]); - }); - }); - - describe('returns an ignored class using specified path in forceignore', () => { - before(async () => { - // forceignore uses a library that wants ignore rules in posix format. - await fs.promises.appendFile( - forceIgnorePath, - `${path.normalize(pathToIgnoredFile1).split(path.sep).join(path.posix.sep)}${os.EOL}` - ); - await fs.promises.appendFile( - forceIgnorePath, - `${path.normalize(pathToIgnoredFile2).split(path.sep).join(path.posix.sep)}${os.EOL}` - ); - }); - after(async () => { - await fs.promises.writeFile(forceIgnorePath, originalForceIgnore); - }); - it('default PkgDir', () => { - const result = execCmd('force:source:ignored:list --json', { ensureExitCode: 0 }).jsonOutput - .result; - expect(result.ignoredFiles).to.include(pathToIgnoredFile1); - expect(result.ignoredFiles).to.include(pathToIgnoredFile2); - }); - it('specified sourcePath', () => { - const result2 = execCmd('force:source:ignored:list --json -p foo-bar', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result2.ignoredFiles).to.include(pathToIgnoredFile1); - expect(result2.ignoredFiles).to.include(pathToIgnoredFile2); - }); - }); - - describe('returns an ignored class using wildcards', () => { - before(async () => { - await fs.promises.appendFile(forceIgnorePath, '**/FooBar.*'); - }); - after(async () => { - await fs.promises.writeFile(forceIgnorePath, originalForceIgnore); - }); - - it('default PkgDir', () => { - const result = execCmd('force:source:ignored:list --json', { ensureExitCode: 0 }).jsonOutput - .result; - expect(result.ignoredFiles).to.include(pathToIgnoredFile1); - expect(result.ignoredFiles).to.include(pathToIgnoredFile2); - }); - it('specified sourcePath', () => { - const result2 = execCmd('force:source:ignored:list --json -p foo-bar', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result2.ignoredFiles).to.include(pathToIgnoredFile1); - expect(result2.ignoredFiles).to.include(pathToIgnoredFile2); - }); - }); - - describe('returns an ignored non-metadata component', () => { - const lwcDir = path.join('foo-bar', 'app', 'lwc'); - const lwcConfigPath = path.join(lwcDir, 'jsconfig.json'); - - before(async () => { - await fs.promises.mkdir(path.join(session.project.dir, lwcDir), { recursive: true }); - await fs.promises.writeFile(path.join(session.project.dir, lwcConfigPath), '{}'); - }); - after(async () => { - await fs.promises.writeFile(forceIgnorePath, originalForceIgnore); - }); - - it('default PkgDir', () => { - const result = execCmd('force:source:ignored:list --json', { ensureExitCode: 0 }).jsonOutput - .result; - expect(result.ignoredFiles).to.include(lwcConfigPath); - }); - it('specified sourcePath', () => { - const result2 = execCmd('force:source:ignored:list --json -p foo-bar', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result2.ignoredFiles).to.include(lwcConfigPath); - }); - }); -}); diff --git a/test/nuts/mdapi.nut.ts b/test/nuts/mdapi.nut.ts index 2c810d309..4883d372d 100644 --- a/test/nuts/mdapi.nut.ts +++ b/test/nuts/mdapi.nut.ts @@ -10,28 +10,15 @@ import * as path from 'path'; import { exec } from 'shelljs'; import { expect } from 'chai'; import { execCmd, ExecCmdResult, TestSession } from '@salesforce/cli-plugins-testkit'; -import { ComponentSet, RequestStatus, SourceComponent } from '@salesforce/source-deploy-retrieve'; +import { RequestStatus } from '@salesforce/source-deploy-retrieve'; import { create as createArchive } from 'archiver'; import { RetrieveCommandAsyncResult, RetrieveCommandResult } from 'src/formatters/mdapi/retrieveResultFormatter'; -import { ConvertCommandResult } from '../../src/formatters/mdapi/convertResultFormatter'; import { DeployCancelCommandResult } from '../../src/formatters/deployCancelResultFormatter'; import { MdDeployResult } from '../../src/formatters/mdapi/mdDeployResultFormatter'; let session: TestSession; - -const writeManifest = (manifestPath: string, contents?: string) => { - contents ??= ` - - - * - ApexClass - - 53.0 -`; - fs.writeFileSync(manifestPath, contents); -}; - -describe('1k files in mdapi:deploy', () => { +// must be skipped while source:convert is moved to PDR +describe.skip('1k files in mdapi:deploy', () => { const classCount = 1000; before(async () => { @@ -85,8 +72,8 @@ describe('1k files in mdapi:deploy', () => { expect(res.result.done).to.be.true; }); }); - -describe('mdapi NUTs', () => { +// must be skipped while source:convert is moved to PDR +describe.skip('mdapi NUTs', () => { before(async () => { session = await TestSession.create({ project: { @@ -120,99 +107,6 @@ describe('mdapi NUTs', () => { await session?.clean(); }); - describe('mdapi:convert', () => { - let convertedToMdPath: string; - - before(() => { - convertedToMdPath = path.join(session.dir, 'convertedToMdPath_dh'); - execCmd(`force:source:convert --json -d ${convertedToMdPath}`, { ensureExitCode: 0 }); - }); - - it('should convert the dreamhouse project', () => { - const convertedToSrcPath = path.join(session.dir, 'convertedToSrcPath_all'); - const result = execCmd( - `force:mdapi:convert -r ${convertedToMdPath} -d ${convertedToSrcPath} --json` - ); - expect(result.jsonOutput.status).to.equal(0); - expect(result.jsonOutput.result).to.be.an('array').with.length.greaterThan(10); - expect(fs.existsSync(convertedToSrcPath)).to.be.true; - }); - - it('should convert the dreamhouse project using metadata flag', () => { - const convertedToSrcPath = path.join(session.dir, 'convertedToSrcPath_metadataFlag'); - const result = execCmd( - `force:mdapi:convert -r ${convertedToMdPath} -d ${convertedToSrcPath} -m ApexClass --json` - ); - expect(result.jsonOutput.status).to.equal(0); - expect(result.jsonOutput.result).to.be.an('array').with.length.greaterThan(10); - expect(fs.existsSync(convertedToSrcPath)).to.be.true; - }); - - it('should convert the dreamhouse project using metadatapath flag', () => { - const convertedToSrcPath = path.join(session.dir, 'convertedToSrcPath_metadatapathFlag'); - const metadataPath = path.join(convertedToMdPath, 'classes', 'PagedResult.cls'); - const result = execCmd( - `force:mdapi:convert -r ${convertedToMdPath} -d ${convertedToSrcPath} -p ${metadataPath} --json` - ); - expect(result.jsonOutput.status).to.equal(0); - expect(result.jsonOutput.result).to.be.an('array').with.lengthOf(2); - expect(fs.existsSync(convertedToSrcPath)).to.be.true; - }); - - it('should convert the dreamhouse project using manifest flag', () => { - const convertedToSrcPath = path.join(session.dir, 'convertedToSrcPath_manifestFlag'); - const manifestPath = path.join(session.dir, 'manifestFlag-package.xml'); - writeManifest(manifestPath); - const result = execCmd( - `force:mdapi:convert -r ${convertedToMdPath} -d ${convertedToSrcPath} -x ${manifestPath} --json` - ); - expect(result.jsonOutput.status).to.equal(0); - expect(result.jsonOutput.result).to.be.an('array').with.length.greaterThan(10); - expect(fs.existsSync(convertedToSrcPath)).to.be.true; - }); - - it('should convert the dreamhouse project and back again', () => { - const convertedToSrcPath = path.join(session.dir, 'convertedToSrcPath_mdapi'); - const convertedToMd2 = path.join(session.dir, 'convertedToMdPath_dh_backAgain'); - const result = execCmd( - `force:mdapi:convert -r ${convertedToMdPath} -d ${convertedToSrcPath} --json` - ); - expect(result.jsonOutput.status).to.equal(0); - expect(fs.existsSync(convertedToSrcPath)).to.be.true; - - // Now source:convert back and compare dirs - execCmd(`force:source:convert --json -r ${convertedToSrcPath} -d ${convertedToMd2}`, { ensureExitCode: 0 }); - - const mdCompSet1 = ComponentSet.fromSource(convertedToMdPath); - const mdCompSet2 = ComponentSet.fromSource(convertedToMd2); - expect(mdCompSet1.size).to.equal(mdCompSet2.size).and.be.greaterThan(10); - for (const comp of mdCompSet1) { - const srcComp2 = mdCompSet2.find( - (c) => c.fullName === comp.fullName && c.type.name === comp.type.name - ) as SourceComponent; - expect(srcComp2).to.be.ok; - const srcComp = comp as SourceComponent; - if (srcComp.xml) { - const size1 = fs.statSync(srcComp.xml).size; - const size2 = fs.statSync(srcComp2.xml).size; - expect(size1).to.equal(size2); - } - if (srcComp.content) { - const stat1 = fs.statSync(srcComp.content); - const stat2 = fs.statSync(srcComp2.content); - - if (stat1.isFile()) { - const size1 = stat1.size; - const size2 = stat2.size; - // Content files can differ slightly due to compression so compare - // with a tolerance. - expect(size1 / size2, `file1 size: ${size1} should ~ equal file2 size: ${size2}`).to.be.within(0.98, 1.02); - } - } - } - }); - }); - describe('mdapi:deploy:cancel', () => { const cancelAssertions = (deployId: string, result: ExecCmdResult): void => { if (result.jsonOutput.status === 0) { diff --git a/test/nuts/partialBundleDelete.nut.ts b/test/nuts/partialBundleDelete.nut.ts index 090129765..6e033637e 100644 --- a/test/nuts/partialBundleDelete.nut.ts +++ b/test/nuts/partialBundleDelete.nut.ts @@ -7,9 +7,8 @@ import * as path from 'path'; import * as fs from 'fs'; import { expect } from 'chai'; -import * as sinon from 'sinon'; import { TestSession, genUniqueString, TestProject, execCmd } from '@salesforce/cli-plugins-testkit'; -import { AuthInfo, Connection } from '@salesforce/core'; +import { AuthInfo, Connection, SfProject } from '@salesforce/core'; import { ComponentSet, ComponentSetBuilder, @@ -18,12 +17,13 @@ import { RetrieveSetOptions, } from '@salesforce/source-deploy-retrieve'; import { RetrieveCommandResult } from 'src/formatters/retrieveResultFormatter'; +import { TestContext } from '@salesforce/core/lib/testSetup'; import { Retrieve } from '../../src/commands/force/source/retrieve'; describe('Partial Bundle Delete Retrieves', () => { let session: TestSession; let projectPath: string; - const sandbox = sinon.createSandbox(); + const sandbox = new TestContext().SANDBOX; const scratchOrgUsername = genUniqueString('pbdr-test-%s@nut.org'); before(async () => { @@ -47,7 +47,7 @@ describe('Partial Bundle Delete Retrieves', () => { }); after(async () => { - await session?.clean(); + // await session?.clean(); }); afterEach(() => { @@ -78,6 +78,9 @@ describe('Partial Bundle Delete Retrieves', () => { const connection = await Connection.create({ authInfo: await AuthInfo.create(session.orgs.get(scratchOrgUsername)), }); + sandbox + .stub(SfProject.prototype, 'getDefaultPackage') + .returns({ name: session.project.dir, path: session.project.dir, fullPath: session.project.dir }); sandbox.stub(connection.metadata, 'retrieve').resolves(retrieveResponse); sandbox.stub(connection.metadata, 'checkRetrieveStatus').resolves(checkRetrieveStatusResponse); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment @@ -96,8 +99,7 @@ describe('Partial Bundle Delete Retrieves', () => { ); return compSet; }); - - const result = (await Retrieve.run(['-p', forgotPasswordDE, '--json'])) as RetrieveCommandResult; + const result = await Retrieve.run(['-p', forgotPasswordDE, '--json', '-o', scratchOrgUsername]); // SDR retrieval code should remove this file expect(fs.existsSync(forgotPasswordTranslationFile)).to.be.false; @@ -282,7 +284,7 @@ const getExpectedCmdJSON = (projectPath: string) => ({ result: { inboundFiles: [ { - fullName: path.join('site', 'source_plugin_nut1.sfdc_cms__view', 'forgotPassword'), + fullName: 'site/source_plugin_nut1.sfdc_cms__view/forgotPassword', type: 'DigitalExperience', state: 'Changed', filePath: path.join( @@ -296,7 +298,7 @@ const getExpectedCmdJSON = (projectPath: string) => ({ ), }, { - fullName: path.join('site', 'source_plugin_nut1.sfdc_cms__view', 'forgotPassword'), + fullName: 'site/source_plugin_nut1.sfdc_cms__view/forgotPassword', type: 'DigitalExperience', state: 'Changed', filePath: path.join( @@ -310,7 +312,7 @@ const getExpectedCmdJSON = (projectPath: string) => ({ ), }, { - fullName: path.join('site', 'source_plugin_nut1.sfdc_cms__view', 'forgotPassword'), + fullName: 'site/source_plugin_nut1.sfdc_cms__view/forgotPassword', type: 'DigitalExperience', state: 'Deleted', filePath: path.join( diff --git a/test/nuts/seeds/convert.seed.ts b/test/nuts/seeds/convert.seed.ts deleted file mode 100644 index 01bf388bf..000000000 --- a/test/nuts/seeds/convert.seed.ts +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import * as fs from 'fs'; -import * as path from 'path'; -import * as shelljs from 'shelljs'; -import { getString } from '@salesforce/ts-types'; -import { SourceTestkit } from '@salesforce/source-testkit'; -import { Result } from '@salesforce/source-testkit/lib/types'; -import { TEST_REPOS_MAP } from '../testMatrix'; - -// DO NOT TOUCH. generateNuts.ts will insert these values -const REPO = TEST_REPOS_MAP.get('%REPO_URL%'); - -context('Convert NUTs [name: %REPO_NAME%]', () => { - let testkit: SourceTestkit; - - before(async () => { - testkit = await SourceTestkit.create({ - repository: REPO.gitUrl, - nut: __filename, - orgless: true, - }); - }); - - after(async () => { - try { - await testkit?.clean(); - } catch (e) { - // if the it fails to clean, don't throw so NUTs will pass - // eslint-disable-next-line no-console - console.log('Clean Failed: ', e); - } - }); - - describe('--manifest flag', () => { - let convertDir: string; - - for (const testCase of REPO.convert.manifest) { - it(`should convert ${testCase.toConvert}`, async () => { - // Generate a package.xml by converting via sourcepath - await testkit.convert({ args: `--sourcepath ${testCase.toConvert} --outputdir out1` }); - const packageXml = path.join('out1', 'package.xml'); - - await testkit.convert({ args: `--manifest ${packageXml} --outputdir out2` }); - await testkit.expect.directoryToHaveSomeFiles('out2'); - await testkit.expect.fileToExist(path.join('out2', 'package.xml')); - await testkit.expect.filesToBeConverted('out2', testCase.toVerify); - }); - - afterEach(() => { - if (convertDir) { - shelljs.rm('-rf', convertDir); - } - }); - } - - for (const testCase of REPO.convert.manifest) { - it(`should convert ${testCase.toConvert} to default output dir`, async () => { - // Generate a package.xml by converting via sourcepath - await testkit.convert({ args: `--sourcepath ${testCase.toConvert}` }); - // should be like metadataPackage_1628780058561 - convertDir = fs.readdirSync(testkit.projectDir).find((files) => files.startsWith('metadataPackage')); - const packageXml = path.join(convertDir, 'package.xml'); - - await testkit.convert({ args: `--manifest ${packageXml} --outputdir out2` }); - await testkit.expect.directoryToHaveSomeFiles('out2'); - await testkit.expect.fileToExist(path.join('out2', 'package.xml')); - await testkit.expect.filesToBeConverted('out2', testCase.toVerify); - }); - - afterEach(() => { - if (convertDir) { - shelljs.rm('-rf', convertDir); - } - }); - } - - for (const testCase of REPO.convert.manifest) { - it(`should convert ${testCase.toConvert} with packagename `, async () => { - const packageName = 'myPackage'; - // Generate a package.xml by converting via sourcepath - await testkit.convert({ - args: `--sourcepath ${testCase.toConvert} --packagename ${packageName} --outputdir out1`, - }); - const packageXml = path.join('out1', 'package.xml'); - - await testkit.convert({ args: `--manifest ${packageXml} --outputdir out2` }); - await testkit.expect.directoryToHaveSomeFiles('out2'); - await testkit.expect.fileToExist(path.join('out2', 'package.xml')); - await testkit.expect.filesToNotExist([path.join('out1', packageName, 'package.xml')]); - await testkit.expect.filesToBeConverted('out2', testCase.toVerify); - }); - - afterEach(() => { - if (convertDir) { - shelljs.rm('-rf', convertDir); - } - }); - } - - it('should throw an error if the package.xml is not valid', async () => { - const convert = (await testkit.convert({ args: '--manifest DOES_NOT_EXIST.xml', exitCode: 1 })) as Result<{ - id: string; - result: { id: string }; - }>; - testkit.expect.errorToHaveName(convert, 'SfError'); - }); - }); - - describe('--metadata flag', () => { - let convertDir: string; - - for (const testCase of REPO.convert.metadata) { - it(`should convert ${testCase.toConvert}`, async () => { - const res = await testkit.convert({ - args: `--metadata ${testCase.toConvert} --outputdir out`, - exitCode: 0, - }); - - convertDir = path.relative(process.cwd(), getString(res, 'result.location') || ''); - await testkit.expect.directoryToHaveSomeFiles(convertDir); - await testkit.expect.fileToExist(path.join(convertDir, 'package.xml')); - await testkit.expect.filesToBeConverted(convertDir, testCase.toVerify); - }); - } - - afterEach(() => { - if (convertDir) { - shelljs.rm('-rf', convertDir); - } - }); - - it('should throw an error if the metadata is not valid', async () => { - const convert = (await testkit.convert({ args: '--metadata DOES_NOT_EXIST', exitCode: 1 })) as Result<{ - id: string; - result: { id: string }; - }>; - - testkit.expect.errorToHaveName(convert, 'SfError'); - testkit.expect.errorToHaveMessage(convert, 'specified metadata type is unsupported'); - }); - }); - - describe('--sourcepath flag', () => { - let convertDir: string; - - for (const testCase of REPO.convert.sourcepath) { - it(`should convert ${testCase.toConvert}`, async () => { - const toConvert = path.normalize(testCase.toConvert); - const res = await testkit.convert({ - args: `--sourcepath ${toConvert} --outputdir out`, - exitCode: 0, - }); - - convertDir = path.relative(process.cwd(), getString(res, 'result.location')); - await testkit.expect.directoryToHaveSomeFiles(convertDir); - await testkit.expect.fileToExist(path.join(convertDir, 'package.xml')); - await testkit.expect.filesToBeConverted(convertDir, testCase.toVerify); - }); - } - - afterEach(() => { - if (convertDir) { - shelljs.rm('-rf', convertDir); - } - }); - - it('should throw an error if the sourcepath is not valid', async () => { - const convert = (await testkit.convert({ args: '--sourcepath DOES_NOT_EXIST', exitCode: 1 })) as Result<{ - id: string; - result: { id: string }; - }>; - - testkit.expect.errorToHaveName(convert, 'SfError'); - testkit.expect.errorToHaveMessage(convert, 'not a valid source file path'); - }); - }); -}); diff --git a/test/nuts/seeds/deploy.async.seed.ts b/test/nuts/seeds/deploy.async.seed.ts index ace80d405..732c00a32 100644 --- a/test/nuts/seeds/deploy.async.seed.ts +++ b/test/nuts/seeds/deploy.async.seed.ts @@ -7,10 +7,10 @@ import { SourceTestkit } from '@salesforce/source-testkit'; import { getBoolean, getString } from '@salesforce/ts-types'; -import { expect } from '@salesforce/command/lib/test'; import { Result } from '@salesforce/source-testkit/lib/types'; import { execCmd } from '@salesforce/cli-plugins-testkit'; import { RequestStatus } from '@salesforce/source-deploy-retrieve'; +import { expect } from 'chai'; import { TEST_REPOS_MAP } from '../testMatrix'; import { DeployCancelCommandResult } from '../../../src/formatters/deployCancelResultFormatter'; diff --git a/test/nuts/seeds/deploy.manifest.seed.ts b/test/nuts/seeds/deploy.manifest.seed.ts index c727e0c33..16ef1508a 100644 --- a/test/nuts/seeds/deploy.manifest.seed.ts +++ b/test/nuts/seeds/deploy.manifest.seed.ts @@ -38,8 +38,8 @@ context('Deploy manifest NUTs [name: %REPO_NAME%]', () => { console.log('Clean Failed: ', e); } }); - - describe('--manifest flag', () => { + // skipping while convert is in PDR and not published + describe.skip('--manifest flag', () => { for (const testCase of REPO.deploy.manifest) { const toDeploy = path.normalize(testCase.toDeploy); it(`should deploy ${toDeploy}`, async () => { diff --git a/test/nuts/seeds/retrieve.manifest.seed.ts b/test/nuts/seeds/retrieve.manifest.seed.ts index 243c2f5f5..c55cf0fa3 100644 --- a/test/nuts/seeds/retrieve.manifest.seed.ts +++ b/test/nuts/seeds/retrieve.manifest.seed.ts @@ -34,8 +34,8 @@ context('Retrieve manifest NUTs [name: %REPO_NAME%]', () => { console.log('Clean Failed: ', e); } }); - - describe('--manifest flag', () => { + // skipping while source:convert is moved to PDR and not published + describe.skip('--manifest flag', () => { let i = 0; for (const testCase of REPO.retrieve.manifest) { const toRetrieve = path.normalize(testCase.toRetrieve); diff --git a/test/nuts/shared/cliForManifestCreate.ts b/test/nuts/shared/cliForManifestCreate.ts new file mode 100644 index 000000000..27d5d40d9 --- /dev/null +++ b/test/nuts/shared/cliForManifestCreate.ts @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +// used temporarily while manifest create is moved out of plugin-source +// TODO: remove this and have these use the "ambient" executable once sf has a manifest generate +export const cliForManifestCreate = 'sfdx'; diff --git a/test/nuts/territory2.nut.ts b/test/nuts/territory2.nut.ts index ed543ea92..cc2ebb6b3 100644 --- a/test/nuts/territory2.nut.ts +++ b/test/nuts/territory2.nut.ts @@ -10,6 +10,7 @@ import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { expect } from 'chai'; import { DeployCommandResult } from '../../src/formatters/deployResultFormatter'; import { RetrieveCommandResult } from '../../src/formatters/retrieveResultFormatter'; +import { cliForManifestCreate } from './shared/cliForManifestCreate'; describe('territories', () => { let session: TestSession; @@ -47,7 +48,7 @@ describe('territories', () => { }); it('can generate manifest for territory types', () => { - execCmd('force:source:manifest:create -p force-app --json', { ensureExitCode: 0 }); + execCmd('force:source:manifest:create -p force-app --json', { ensureExitCode: 0, cli: cliForManifestCreate }); expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.true; }); diff --git a/test/nuts/trackingCommands/deployRetrieveDelete.nut.ts b/test/nuts/trackingCommands/deployRetrieveDelete.nut.ts index ad99dc741..08bde6c9c 100644 --- a/test/nuts/trackingCommands/deployRetrieveDelete.nut.ts +++ b/test/nuts/trackingCommands/deployRetrieveDelete.nut.ts @@ -91,24 +91,4 @@ describe('-t flag for deploy, retrieve, and delete', () => { ).to.have.length(0); }); }); - describe('delete', () => { - it('can delete remote and local metadata with tracking', async () => { - const result = execCmd('force:source:delete -m ApexClass:FooBarTest -t --noprompt --json', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result.deletedSource).to.be.an.instanceof(Array).with.length.greaterThan(0); - expect(result.deletedSource.every((item) => item.type === 'ApexClass')).to.equal(true); - }); - - it('sees no local or remote changes', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - }).jsonOutput.result; - // this delete WILL change the admin profile, so remove that from the status result - expect( - result.filter((r) => r.type === 'ApexClass'), - JSON.stringify(result) - ).to.have.length(0); - }); - }); }); diff --git a/test/nuts/trackingCommands/resetClear.nut.ts b/test/nuts/trackingCommands/resetClear.nut.ts deleted file mode 100644 index 88b646837..000000000 --- a/test/nuts/trackingCommands/resetClear.nut.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2020, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ - -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ - -import * as path from 'path'; -import * as fs from 'fs'; - -import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; -import { expect } from 'chai'; -import { AuthInfo, Connection } from '@salesforce/core'; -import { StatusResult } from '../../../src/formatters/source/statusFormatter'; -import { SourceTrackingClearResult } from '../../../src/commands/force/source/tracking/clear'; - -let session: TestSession; -let orgId: string; -let trackingFileFolder: string; -let conn: Connection; - -// copy/pasted here to avoid exporting this type from STL -type MemberRevision = { - serverRevisionCounter: number; - lastRetrievedFromServer: number | null; - memberType: string; - isNameObsolete: boolean; -}; - -const getRevisionsAsArray = async (): Promise => { - const revisionFile = JSON.parse( - await fs.promises.readFile(path.join(trackingFileFolder, 'maxRevision.json'), 'utf8') - ) as Record; - return Reflect.ownKeys(revisionFile.sourceMembers).map((key) => revisionFile.sourceMembers[key] as MemberRevision); -}; - -describe('reset and clear', () => { - before(async () => { - session = await TestSession.create({ - project: { - gitClone: 'https://github.com/trailheadapps/ebikes-lwc', - }, - devhubAuthStrategy: 'AUTO', - scratchOrgs: [ - { - executable: 'sfdx', - duration: 1, - setDefault: true, - config: path.join('config', 'project-scratch-def.json'), - }, - ], - }); - - orgId = session.orgs.get('default').orgId; - trackingFileFolder = path.join(session?.project.dir, '.sf', 'orgs', orgId); - conn = await Connection.create({ - authInfo: await AuthInfo.create({ - username: session.orgs.get('default').username, - }), - }); - }); - - after(async () => { - await session?.zip(undefined, 'artifacts'); - await session?.clean(); - }); - - describe('clearing tracking', () => { - it('runs status to start tracking', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(result).to.have.length.greaterThan(100); // ebikes is big - }); - - it('local tracking file exists', () => { - expect(fs.existsSync(path.join(trackingFileFolder, 'localSourceTracking'))).to.equal(true); - }); - it('remote tracking file exists', () => { - expect(fs.existsSync(path.join(trackingFileFolder, 'maxRevision.json'))).to.equal(true); - }); - it('runs clear', () => { - const clearResult = execCmd('force:source:tracking:clear --noprompt --json', { - ensureExitCode: 0, - }).jsonOutput.result; - expect(clearResult.clearedFiles.some((file) => file.includes('maxRevision.json'))).to.equal(true); - }); - it('local tracking is gone', () => { - expect(fs.existsSync(path.join(trackingFileFolder, 'localSourceTracking'))).to.equal(false); - }); - it('remote tracking is gone', () => { - expect(fs.existsSync(path.join(trackingFileFolder, 'maxRevision.json'))).to.equal(false); - }); - }); - - describe('reset remote tracking', () => { - let lowestRevision = 0; - it('creates 2 apex classes to get some tracking going', async () => { - const createResult = await conn.tooling.create('ApexClass', { - Name: 'CreatedClass', - Body: 'public class CreatedClass {}', - Status: 'Active', - }); - const createResult2 = await conn.tooling.create('ApexClass', { - Name: 'CreatedClass2', - Body: 'public class CreatedClass2 {}', - Status: 'Active', - }); - [createResult, createResult2].map((result) => { - if (!Array.isArray(result)) { - expect(result.success).to.equal(true); - } - }); - // gets tracking files from server - execCmd('force:source:status --json --remote', { ensureExitCode: 0 }); - const revisions = await getRevisionsAsArray(); - const revisionFile = JSON.parse( - await fs.promises.readFile(path.join(trackingFileFolder, 'maxRevision.json'), 'utf8') - ); - lowestRevision = revisions.reduce( - (previousValue: number, revision) => Math.min(previousValue, revision.serverRevisionCounter), - revisionFile.serverMaxRevisionCounter - ); - expect(lowestRevision).lessThan(revisionFile.serverMaxRevisionCounter as number); - // revisions are not retrieved - revisions.map((revision) => { - expect(revision.serverRevisionCounter).to.not.equal(revision.lastRetrievedFromServer); - expect(revision.lastRetrievedFromServer).to.equal(null); - }); - }); - it('can reset to a known revision', async () => { - execCmd(`force:source:tracking:reset --revision ${lowestRevision} --noprompt`, { - ensureExitCode: 0, - }); - const revisions = await getRevisionsAsArray(); - - revisions.map((revision) => { - revision.serverRevisionCounter === lowestRevision - ? expect(revision.serverRevisionCounter).to.equal(revision.lastRetrievedFromServer) - : expect(revision.serverRevisionCounter).to.not.equal(revision.lastRetrievedFromServer); - }); - }); - - it('can reset to a non-specified revision (resets everything)', async () => { - execCmd(`force:source:tracking:reset --revision ${lowestRevision} --noprompt`, { - ensureExitCode: 0, - }); - const revisions = await getRevisionsAsArray(); - - revisions.map((revision) => { - expect(revision.serverRevisionCounter === revision.lastRetrievedFromServer).to.equal(true); - }); - }); - }); -}); diff --git a/test/nuts/translation.nut.ts b/test/nuts/translation.nut.ts index 41281df48..e8c6c79f8 100644 --- a/test/nuts/translation.nut.ts +++ b/test/nuts/translation.nut.ts @@ -12,6 +12,7 @@ import { PushResponse } from 'src/formatters/source/pushResultFormatter'; import { DeployCommandResult } from '../../src/formatters/deployResultFormatter'; import { RetrieveCommandResult } from '../../src/formatters/retrieveResultFormatter'; import { StatusResult } from '../../src/formatters/source/statusFormatter'; +import { cliForManifestCreate } from './shared/cliForManifestCreate'; describe('translations', () => { let session: TestSession; @@ -80,7 +81,7 @@ describe('translations', () => { }); it('can generate manifest for translation types', async () => { - execCmd('force:source:manifest:create -p force-app --json', { ensureExitCode: 0 }); + execCmd('force:source:manifest:create -p force-app --json', { ensureExitCode: 0, cli: cliForManifestCreate }); expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.true; }); @@ -187,7 +188,7 @@ describe('translations', () => { describe('mdapi format', () => { it('can convert COT/CFTs correctly', () => { - execCmd('force:source:convert --outputdir mdapi', { ensureExitCode: 0 }); + execCmd('force:source:convert --outputdir mdapi', { ensureExitCode: 0, cli: cliForManifestCreate }); // the CFTs shouldn't be written to mdapi format expect(fs.existsSync(path.join(session.project.dir, 'mdapi', 'fields'))).to.be.false; expect(fs.existsSync(path.join(session.project.dir, 'mdapi', 'objectTranslations'))).to.be.true; diff --git a/yarn.lock b/yarn.lock index 73983b5db..3ec76cb6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -395,6 +395,13 @@ esquery "^1.4.0" jsdoc-type-pratt-parser "~3.1.0" +"@eslint-community/eslint-utils@^4.2.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz#a556790523a351b4e47e9d385f47265eaaf9780a" + integrity sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA== + dependencies: + eslint-visitor-keys "^3.3.0" + "@eslint/eslintrc@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" @@ -431,7 +438,7 @@ "@humanwhocodes/object-schema@^1.2.1": version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@isaacs/string-locale-compare@^1.1.0": @@ -681,7 +688,7 @@ supports-color "^8.1.1" tslib "^2" -"@oclif/core@^1.20.3", "@oclif/core@^1.20.4", "@oclif/core@^1.23.1", "@oclif/core@^1.25.0", "@oclif/core@^1.9.9": +"@oclif/core@^1.20.3", "@oclif/core@^1.20.4": version "1.26.1" resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.26.1.tgz#26e46c96143d3e2b1dd9bd558ae1653fe9a4f3fa" integrity sha512-g+OWJcM7JOVI53caTEtq0BB1nPotWctRLUyFODPgvDqXhVR7QED+Qz3LwFAMD8dt7/Ar2ZNq15U3bnpnOv453A== @@ -715,10 +722,10 @@ widest-line "^3.1.0" wrap-ansi "^7.0.0" -"@oclif/core@^2.0.8", "@oclif/core@^2.1.7", "@oclif/core@^2.3.0", "@oclif/core@^2.3.1", "@oclif/core@^2.4.0", "@oclif/core@^2.6.2": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@oclif/core/-/core-2.7.1.tgz#3f38c1ace1675d80b0bbaa3ae5d4572b8fa04c22" - integrity sha512-HnaZ0ezNJUGok4uACOmVl05aSrCblmuq5Sqyg3Qa8aLFnTBuvHn3d67fTJKSttyAnJ5LI3zw8e5vzLD7WZuP0A== +"@oclif/core@^2.0.7", "@oclif/core@^2.1.7", "@oclif/core@^2.3.0", "@oclif/core@^2.3.1", "@oclif/core@^2.4.0", "@oclif/core@^2.6.2", "@oclif/core@^2.6.3": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@oclif/core/-/core-2.8.0.tgz#4948de3168804169fa68895af8ec4853f332b307" + integrity sha512-A2wHItFrD/WOw5bJ6Mtv9MD7If0bsKNR0pwEY0me+fo4HSXlJOtgYGqmzb8t8akX3DUUT7XsjPajsoHLkIJyvg== dependencies: "@types/cli-progress" "^3.11.0" ansi-escapes "^4.3.2" @@ -803,14 +810,6 @@ resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-3.0.4.tgz#663db0ecaf23f3184e7f01886ed578060e4a7f1c" integrity sha512-IMsTN1dXEXaOSre27j/ywGbBjrzx0FNd1XmuhCWCB9NTPrhWI1Ifbz+YLSEcstfQfocYsrbrIessxXb2oon4lA== -"@oclif/test@^2.2.21": - version "2.3.5" - resolved "https://registry.yarnpkg.com/@oclif/test/-/test-2.3.5.tgz#270ef891c3491dff4cc29df756deb776291602e5" - integrity sha512-LxmiatZV7Ph9K2F0Rs0u2d7BODxbfL7qfHE94HwqzaW8uRe20JbGMxH4iGBHFE5Gdod6XIV3o3jHyPXVlz7YZA== - dependencies: - "@oclif/core" "^2.0.8" - fancy-test "^2.0.12" - "@octokit/auth-token@^2.4.4": version "2.5.0" resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" @@ -954,26 +953,14 @@ strip-ansi "6.0.1" ts-retry-promise "^0.7.0" -"@salesforce/command@^5.3.0", "@salesforce/command@^5.3.3": - version "5.3.3" - resolved "https://registry.yarnpkg.com/@salesforce/command/-/command-5.3.3.tgz#863380090d8febeb803ceb32690302c490ffe1fc" - integrity sha512-p6I5AiQG85Ptk6hxh0r9Xg34MTshnGmDkGSY+S1yqodOF8oV+frCnUenInjwibxyuSqL0hPm+scx8/jwhqLNVA== - dependencies: - "@oclif/core" "^1.25.0" - "@oclif/test" "^2.2.21" - "@salesforce/core" "^3.33.6" - "@salesforce/kit" "^1.8.5" - "@salesforce/ts-types" "^1.7.1" - chalk "^2.4.2" - -"@salesforce/core@^3.23.9", "@salesforce/core@^3.24.0", "@salesforce/core@^3.32.12", "@salesforce/core@^3.33.1", "@salesforce/core@^3.33.4", "@salesforce/core@^3.33.5", "@salesforce/core@^3.33.6", "@salesforce/core@^3.34.1": - version "3.34.4" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.34.4.tgz#6fa11c32f14d20130a0c92c5d306f368671ec104" - integrity sha512-WasR/6IXKcNj3MgZIcVaT7W5Ic/blxOgpQIzob/7JEsnLVr3pPPb+9/axRvxEGdJr/gOnL1vR0NbBX+Mz6TtkQ== +"@salesforce/core@^3.24.0", "@salesforce/core@^3.32.12", "@salesforce/core@^3.33.1", "@salesforce/core@^3.33.4", "@salesforce/core@^3.33.5", "@salesforce/core@^3.33.6", "@salesforce/core@^3.34.1", "@salesforce/core@^3.34.4": + version "3.34.6" + resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.34.6.tgz#816031d3aab098d56165d876db626a3610d86c6e" + integrity sha512-9Nd+bQRSvCYDiZo97bhseajLhr7d51J9gsPUnfN3nHy1/TBQXjN+upRAPAeldvzU8G3L98WGDMtEpSTOG/PxkQ== dependencies: "@salesforce/bunyan" "^2.0.0" "@salesforce/kit" "^1.9.2" - "@salesforce/schemas" "^1.5.0" + "@salesforce/schemas" "^1.5.1" "@salesforce/ts-types" "^1.7.2" "@types/graceful-fs" "^4.1.6" "@types/semver" "^7.3.13" @@ -1034,7 +1021,7 @@ typescript "^4.1.3" wireit "^0.9.5" -"@salesforce/kit@^1.7.1", "@salesforce/kit@^1.8.0", "@salesforce/kit@^1.8.3", "@salesforce/kit@^1.8.5", "@salesforce/kit@^1.9.0", "@salesforce/kit@^1.9.2": +"@salesforce/kit@^1.7.1", "@salesforce/kit@^1.8.0", "@salesforce/kit@^1.8.2", "@salesforce/kit@^1.8.3", "@salesforce/kit@^1.9.0", "@salesforce/kit@^1.9.2": version "1.9.2" resolved "https://registry.yarnpkg.com/@salesforce/kit/-/kit-1.9.2.tgz#d232f135428363cdfe2649cb99a94bc2eb0a12fd" integrity sha512-kjZvjFNP6njhAiEa/ErdLXSDWZKafHYJyKCKz1wnSFmDM8TOpKHCCVw5cQo87ZQr8OqxqwUDIAlSBLyMzKi4Lg== @@ -1043,29 +1030,21 @@ shx "^0.3.3" tslib "^2.5.0" -"@salesforce/plugin-command-reference@^1.6.6": - version "1.6.6" - resolved "https://registry.yarnpkg.com/@salesforce/plugin-command-reference/-/plugin-command-reference-1.6.6.tgz#16406861e49270a3889a8813b09c45dbff4cc4cd" - integrity sha512-4jO3wx+ceJZ4OevaROH2qKySGF+mE6rifbIXPzOQhVFZIlCUYyt1rEF7RNBAbvtBUazDgBCQ6Y8sZVkTl5JcLQ== +"@salesforce/plugin-command-reference@^2.3.2": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@salesforce/plugin-command-reference/-/plugin-command-reference-2.4.1.tgz#eb004d17728908ab2f7fd9554ee06f89258f300b" + integrity sha512-4MWvZSb8wSwY4N1hL3E7qyH9ONJ/tGcOtmqTdtwypp7r/GkapnezfwiQcexkhlwrDqUhkCG2h+r3YW/kUryGiA== dependencies: - "@salesforce/command" "^5.3.3" - "@salesforce/core" "^3.33.6" - "@types/lodash.uniqby" "^4.7.7" + "@oclif/core" "^2.0.7" + "@salesforce/core" "^3.32.12" + "@salesforce/kit" "^1.8.2" + "@salesforce/sf-plugins-core" "^2.0.1" + "@salesforce/ts-types" "^1.7.1" chalk "^3.0.0" - handlebars "4.7.7" + fs-extra "^10.0.1" + handlebars "^4.7.7" lodash.uniqby "^4.7.0" - shelljs "^0.8.5" - tslib "^2" - -"@salesforce/plugin-config@^2.3.2": - version "2.3.3" - resolved "https://registry.npmjs.org/@salesforce/plugin-config/-/plugin-config-2.3.3.tgz#661b1af515d3300207cc9441f2586d2c7e3df597" - integrity sha512-s2i8xVofXAXRo8hpHfSMtCWUaPJSeLEWqO0jBfxtepAL0BBqEKW7zD/dhD2s3hHPrQ3OOPy0bVPAx33gJCe9xg== - dependencies: - "@oclif/core" "^1.9.9" - "@salesforce/core" "^3.23.9" - "@salesforce/sf-plugins-core" "^1.13.0" - chalk "^4.1.1" + mkdirp "^1.0.4" tslib "^2" "@salesforce/plugin-info@^2.5.1": @@ -1086,6 +1065,17 @@ semver "^7.3.5" tslib "^2" +"@salesforce/plugin-settings@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@salesforce/plugin-settings/-/plugin-settings-1.4.2.tgz#e99be8b141c27431b379ee3f1f878453cc9cad19" + integrity sha512-uEgxHlblJOz68ETpnK+aQv9KwNpCN8D3YYOeCtyNC4R1zPa2spz7mz/565F8tuUmZgHePLD1e/vz6vS/9OeI+w== + dependencies: + "@oclif/core" "^2.3.0" + "@salesforce/core" "^3.33.4" + "@salesforce/sf-plugins-core" "^2.2.4" + fast-levenshtein "^3.0.0" + tslib "^2" + "@salesforce/plugin-templates@^55.4.4": version "55.4.4" resolved "https://registry.yarnpkg.com/@salesforce/plugin-templates/-/plugin-templates-55.4.4.tgz#951526492afa4ff8c07b3efb81ebde41181796ba" @@ -1116,47 +1106,35 @@ resolved "https://registry.npmjs.org/@salesforce/prettier-config/-/prettier-config-0.0.2.tgz#ded39bf7cb75238edc9db6dd093649111350f8bc" integrity sha512-KExM355BLbxCW6siGBV7oUOotXvvVp0tAWERgzUkM2FcMb9fWrjwXDrIHc8V0UdDlA3UXtFltDWgN+Yqi+BA/g== -"@salesforce/schemas@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.5.0.tgz#8bfe2cb5d7cb29d3394b3b9cfb71bb527009c82c" - integrity sha512-EKFBURBuON7cj8XZCW+ybeSRRw7wUP1XUXZVHzFgx8KiYmSeGiRHBYbDjQOsQMho2uOLsTozMPEt2ehYnji0YA== - -"@salesforce/sf-plugins-core@^1.13.0": - version "1.22.1" - resolved "https://registry.yarnpkg.com/@salesforce/sf-plugins-core/-/sf-plugins-core-1.22.1.tgz#58c445aa8c72ae7ddd6ec39269ae1d944d059e9b" - integrity sha512-UAAi7I753+t9zVJDHMzk81XCsYU5q2kq7aSgFbokdvnnPx45i3NptyaKNCRDeOBxp3eYCuNG6iFZ+xzC+v8cfA== - dependencies: - "@oclif/core" "^1.23.1" - "@salesforce/core" "^3.32.12" - "@salesforce/kit" "^1.7.1" - "@salesforce/ts-types" "^1.7.1" - chalk "^4" - inquirer "^8.2.5" +"@salesforce/schemas@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.5.1.tgz#2d1bfdcf593caaa04cd4b3e6fe621097ff7f28fe" + integrity sha512-MRqU+tn8w5IFvZ0Lm9YKLgxYxr2MQMI+fXXsTrwfUnijsps+ybF9IOTu6MOMxxl2vCUkO8XDjA435wXlWSLI6g== -"@salesforce/sf-plugins-core@^2.0.2", "@salesforce/sf-plugins-core@^2.2.3", "@salesforce/sf-plugins-core@^2.2.4": - version "2.2.5" - resolved "https://registry.yarnpkg.com/@salesforce/sf-plugins-core/-/sf-plugins-core-2.2.5.tgz#cc20c6f18f15c173b6bc3b511a56c09f155675df" - integrity sha512-9CINVi3akBDreUpoz1J9QhZphKJWqq86m7aJxMPPTIh0cHAdJ4qi4KcdP4Tmwub2BUTYdbibYzix7kpRM0MkwA== +"@salesforce/sf-plugins-core@^2.0.1", "@salesforce/sf-plugins-core@^2.0.2", "@salesforce/sf-plugins-core@^2.2.3", "@salesforce/sf-plugins-core@^2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@salesforce/sf-plugins-core/-/sf-plugins-core-2.2.4.tgz#c94f83cab62ff0009b88069e72b4cdcfc9748b82" + integrity sha512-lKi0W4y3SJfZCT1cuWZsc6vbJLS+QwO4TMbu/dob0LIba7r3+nrd7st8t2xvm/Z3hRKr8xsJADq/XFYPU7jfmQ== dependencies: "@oclif/core" "^2.4.0" - "@salesforce/core" "^3.34.1" + "@salesforce/core" "^3.33.5" "@salesforce/kit" "^1.9.0" "@salesforce/ts-types" "^1.7.3" chalk "^4" inquirer "^8.2.5" -"@salesforce/source-deploy-retrieve@^7.10.1", "@salesforce/source-deploy-retrieve@^7.11.3": - version "7.11.3" - resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-7.11.3.tgz#17d63abd0b0d33de1ac9585fcc294235cb42429e" - integrity sha512-d5kVkLcqJBFNaPIWZlKKAExKo/HbQ2ycDsWyDlpxyweox2t2wMc+YLCvxOzhk1x+UnQmHWiSS7JaoTExM/Dx3Q== +"@salesforce/source-deploy-retrieve@^7.10.1", "@salesforce/source-deploy-retrieve@^7.11.3", "@salesforce/source-deploy-retrieve@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-7.14.2.tgz#39ae1d7506544d22e787ec6b1fedfa2d86ff3ccf" + integrity sha512-AgwpTYUh4y7+mz8nY1okkiCCX+L1yC2hXGDcpIlaWQOVqiX8a2ZBFmd4Suq1WluPhRDg6Awztky1L/tHH6VUMw== dependencies: - "@salesforce/core" "^3.33.1" + "@salesforce/core" "^3.34.4" "@salesforce/kit" "^1.9.0" "@salesforce/ts-types" "^1.7.2" archiver "^5.3.1" fast-xml-parser "^3.21.1" got "^11.8.6" - graceful-fs "^4.2.10" + graceful-fs "^4.2.11" ignore "^5.2.4" mime "2.6.0" minimatch "^5.1.6" @@ -1305,71 +1283,71 @@ resolved "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== -"@swc/core-darwin-arm64@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.42.tgz#fabb645b288199b730d846e3eda370b77f5ebe9f" - integrity sha512-hM6RrZFyoCM9mX3cj/zM5oXwhAqjUdOCLXJx7KTQps7NIkv/Qjvobgvyf2gAb89j3ARNo9NdIoLjTjJ6oALtiA== - -"@swc/core-darwin-x64@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.42.tgz#dcd434ec8dda6f2178a10da0def036a071a6e008" - integrity sha512-bjsWtHMb6wJK1+RGlBs2USvgZ0txlMk11y0qBLKo32gLKTqzUwRw0Fmfzuf6Ue2a/w//7eqMlPFEre4LvJajGw== - -"@swc/core-linux-arm-gnueabihf@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.42.tgz#59c57b15113d316e8a4a6d690a6c09429483d201" - integrity sha512-Oe0ggMz3MyqXNfeVmY+bBTL0hFSNY3bx8dhcqsh4vXk/ZVGse94QoC4dd92LuPHmKT0x6nsUzB86x2jU9QHW5g== - -"@swc/core-linux-arm64-gnu@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.42.tgz#50d026b9f4d7a5f25deacc8c8dd45fc12be70a95" - integrity sha512-ZJsa8NIW1RLmmHGTJCbM7OPSbBZ9rOMrLqDtUOGrT0uoJXZnnQqolflamB5wviW0X6h3Z3/PSTNGNDCJ3u3Lqg== - -"@swc/core-linux-arm64-musl@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.42.tgz#3c0e51b0709dcf06289949803c9a36a46a97827c" - integrity sha512-YpZwlFAfOp5vkm/uVUJX1O7N3yJDO1fDQRWqsOPPNyIJkI2ydlRQtgN6ZylC159Qv+TimfXnGTlNr7o3iBAqjg== - -"@swc/core-linux-x64-gnu@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.42.tgz#059ac0acddebd0360851871929a14dbacf74f865" - integrity sha512-0ccpKnsZbyHBzaQFdP8U9i29nvOfKitm6oJfdJzlqsY/jCqwvD8kv2CAKSK8WhJz//ExI2LqNrDI0yazx5j7+A== - -"@swc/core-linux-x64-musl@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.42.tgz#7a61093d93a3abc2f893b7d31fd6c22c4cab2212" - integrity sha512-7eckRRuTZ6+3K21uyfXXgc2ZCg0mSWRRNwNT3wap2bYkKPeqTgb8pm8xYSZNEiMuDonHEat6XCCV36lFY6kOdQ== - -"@swc/core-win32-arm64-msvc@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.42.tgz#12f92c960ea801aa26ffa5b91d369ac24c2a3cca" - integrity sha512-t27dJkdw0GWANdN4TV0lY/V5vTYSx5SRjyzzZolep358ueCGuN1XFf1R0JcCbd1ojosnkQg2L7A7991UjXingg== - -"@swc/core-win32-ia32-msvc@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.42.tgz#be022aff03838515fa5506be300f0ea15f3fb476" - integrity sha512-xfpc/Zt/aMILX4IX0e3loZaFyrae37u3MJCv1gJxgqrpeLi7efIQr3AmERkTK3mxTO6R5urSliWw2W3FyZ7D3Q== - -"@swc/core-win32-x64-msvc@1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.42.tgz#fccac26974f03234e502276389f4330e2696887f" - integrity sha512-ra2K4Tu++EJLPhzZ6L8hWUsk94TdK/2UKhL9dzCBhtzKUixsGCEqhtqH1zISXNvW8qaVLFIMUP37ULe80/IJaA== - -"@swc/core@^1.3.42": - version "1.3.42" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.42.tgz#7067c4fd9a02536f9ca7b54ed8ebc45e2df810cf" - integrity sha512-nVFUd5+7tGniM2cT3LXaqnu3735Cu4az8A9gAKK+8sdpASI52SWuqfDBmjFCK9xG90MiVDVp2PTZr0BWqCIzpw== +"@swc/core-darwin-arm64@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.39.tgz#7c6e87dc8b27ce406eeb5d5cd39bde9fe06f416c" + integrity sha512-qYR47BEfUvK1WRAP/LVbHakCo4mcksgDjRutJbkx3maTgHlSGYQKCQo7hz+or+n3cbR2abY0rFEgoCLjZctGOw== + +"@swc/core-darwin-x64@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.39.tgz#709f269e2af553b16d35a702c90553ef0af3e400" + integrity sha512-kqJ8OleY/y3S+HXnZxDWFVbKpRsb7gZDZr6Pksr8tzFba/6pLkZFBxds/zgfWIlUwri2Lcx0X872MJ46ghwv9w== + +"@swc/core-linux-arm-gnueabihf@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.39.tgz#04e83e963ecf42228994bee3028f74b17a871456" + integrity sha512-+c3A2BV0esPNHn/KKMqP+bphUF86sVKUIaxn5tKMDrnO8ckOpEMbJ+SwzYLtwC9JIYjWwryg/0yvWrdma26Irw== + +"@swc/core-linux-arm64-gnu@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.39.tgz#fae7fa25a1b22ea51ce53d9982ffbb17c99f7071" + integrity sha512-IRrfft7ANk3NR0qX6bXbfkqbT+WR0TMvgODQdZAtRQIt5ERFpdhcnYc4tlJzfV23R0Ek3kpdA8Gduj4tHk0K6w== + +"@swc/core-linux-arm64-musl@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.39.tgz#74544b4fe31c708e5baad73a6ca52c6f9de4b4c1" + integrity sha512-N8tnynqBdRzY8m2blPAnLUtaln0m8gb96q6ipnY+XoHQ3Z6uZoUq8jWAeFDhD+MCzM7qD2HyBDN7sEqiwMRO/g== + +"@swc/core-linux-x64-gnu@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.39.tgz#8b8345d7080dbbda3e673ce21419bae4fc7cd214" + integrity sha512-Jif56kWHOjQexCib4FVbGeUcBUc56cgNW7ELEKAUCID70z20JHMVTd5utcmfi1L9tywGMvfzqD5z+NQtrFV8GQ== + +"@swc/core-linux-x64-musl@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.39.tgz#70d00f78ec1695b8d6581b0a885ac9ba1bca3867" + integrity sha512-ZiGERr/mdsEwfSiWn2Qokd8a4TTJkLVta6Nan39Bozo6J789u4uDF9Cj5TWWMSanHYAK/oRDaUm1yo2/DSecAA== + +"@swc/core-win32-arm64-msvc@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.39.tgz#9f35782f008a722f8ae230766e16e426f2b146f9" + integrity sha512-eUAk12LZ6RQHhe0ikZZsi0CPbRA6qsvoNQQ/6uwVF60CT0UnJrLiX3w3q30aXK3WjVR6uUlVEn7ze5t7HUeGyQ== + +"@swc/core-win32-ia32-msvc@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.39.tgz#3964c477d542ac41990c8cb12558d6f616cc3d64" + integrity sha512-c3MIt+0gvZD0hmPOyoIJtdgx1ubP7E+uUnljw2+Nk8rO6qhIrWI08tWRNbT0HNLXHfHhKMJHvSAg3DGW8vG3Rg== + +"@swc/core-win32-x64-msvc@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.39.tgz#81344093a5e4b4e24894b1abcf35689f3838b5c2" + integrity sha512-c4xGToLavhHjrE0Um0GyXCilL3sKNRP71GgQTVvqTFHxMmdUCBdug28olMDE1gYsCqXHaF6rPtg3QmD6dhTzKQ== + +"@swc/core@1.3.39": + version "1.3.39" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.39.tgz#c59f92dc116cf32a08d788aa5e0ce7eb856e3d40" + integrity sha512-r5oIySPo2OkC14+gmhK5H1HnDEgOvj5kx6Ogxa+Og7KyWIHE8l1JjjW+4wzYdjxtdhRjVRhvoI6mPQNQz/btBg== optionalDependencies: - "@swc/core-darwin-arm64" "1.3.42" - "@swc/core-darwin-x64" "1.3.42" - "@swc/core-linux-arm-gnueabihf" "1.3.42" - "@swc/core-linux-arm64-gnu" "1.3.42" - "@swc/core-linux-arm64-musl" "1.3.42" - "@swc/core-linux-x64-gnu" "1.3.42" - "@swc/core-linux-x64-musl" "1.3.42" - "@swc/core-win32-arm64-msvc" "1.3.42" - "@swc/core-win32-ia32-msvc" "1.3.42" - "@swc/core-win32-x64-msvc" "1.3.42" + "@swc/core-darwin-arm64" "1.3.39" + "@swc/core-darwin-x64" "1.3.39" + "@swc/core-linux-arm-gnueabihf" "1.3.39" + "@swc/core-linux-arm64-gnu" "1.3.39" + "@swc/core-linux-arm64-musl" "1.3.39" + "@swc/core-linux-x64-gnu" "1.3.39" + "@swc/core-linux-x64-musl" "1.3.39" + "@swc/core-win32-arm64-msvc" "1.3.39" + "@swc/core-win32-ia32-msvc" "1.3.39" + "@swc/core-win32-x64-msvc" "1.3.39" "@szmarczak/http-timer@^4.0.5": version "4.0.6" @@ -1425,7 +1403,7 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/chai@*", "@types/chai@^4.2.11": +"@types/chai@^4.2.11": version "4.3.4" resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== @@ -1505,18 +1483,6 @@ dependencies: "@types/node" "*" -"@types/lodash.uniqby@^4.7.7": - version "4.7.7" - resolved "https://registry.npmjs.org/@types/lodash.uniqby/-/lodash.uniqby-4.7.7.tgz#48dbb652c41cc8fb30aa61a44174368081835ab5" - integrity sha512-sv2g6vkCIvEUsK5/Vq17haoZaisfj2EWW8mP7QWlnKi6dByoNmeuHDDXHR7sabuDqwO4gvU7ModIL22MmnOocg== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.189" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz#975ff8c38da5ae58b751127b19ad5e44b5b7f6d2" - integrity sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA== - "@types/minimatch@*": version "5.1.2" resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" @@ -1594,13 +1560,6 @@ "@types/glob" "*" "@types/node" "*" -"@types/sinon@*": - version "10.0.13" - resolved "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" - integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - "@types/sinon@10.0.11": version "10.0.11" resolved "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42" @@ -1662,6 +1621,14 @@ "@typescript-eslint/types" "5.54.0" "@typescript-eslint/visitor-keys" "5.54.0" +"@typescript-eslint/scope-manager@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz#e863bab4d4183ddce79967fe10ceb6c829791210" + integrity sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw== + dependencies: + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/visitor-keys" "5.55.0" + "@typescript-eslint/type-utils@5.43.0": version "5.43.0" resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz#91110fb827df5161209ecca06f70d19a96030be6" @@ -1682,6 +1649,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.0.tgz#7d519df01f50739254d89378e0dcac504cab2740" integrity sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ== +"@typescript-eslint/types@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.55.0.tgz#9830f8d3bcbecf59d12f821e5bc6960baaed41fd" + integrity sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug== + "@typescript-eslint/typescript-estree@5.43.0": version "5.43.0" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz#b6883e58ba236a602c334be116bfc00b58b3b9f2" @@ -1708,6 +1680,19 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz#8db7c8e47ecc03d49b05362b8db6f1345ee7b575" + integrity sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ== + dependencies: + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/visitor-keys" "5.55.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/utils@5.43.0": version "5.43.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz#00fdeea07811dbdf68774a6f6eacfee17fcc669f" @@ -1722,6 +1707,20 @@ eslint-utils "^3.0.0" semver "^7.3.7" +"@typescript-eslint/utils@^5.54.1": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.55.0.tgz#34e97322e7ae5b901e7a870aabb01dad90023341" + integrity sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.55.0" + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/typescript-estree" "5.55.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + "@typescript-eslint/visitor-keys@5.43.0": version "5.43.0" resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz#cbbdadfdfea385310a20a962afda728ea106befa" @@ -1738,6 +1737,14 @@ "@typescript-eslint/types" "5.54.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz#01ad414fca8367706d76cdb94adf788dc5b664a2" + integrity sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw== + dependencies: + "@typescript-eslint/types" "5.55.0" + eslint-visitor-keys "^3.3.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -1765,7 +1772,7 @@ abort-controller@^3.0.0: acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1, acorn-walk@^8.2.0: @@ -1812,17 +1819,7 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.11.0: - version "8.11.2" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" - integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ajv@^8.12.0: +ajv@^8.11.0, ajv@^8.12.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -2431,7 +2428,7 @@ chalk@^1.0.0: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3431,6 +3428,14 @@ eslint-plugin-prefer-arrow@^1.2.1: resolved "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz#e7fbb3fa4cd84ff1015b9c51ad86550e55041041" integrity sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ== +eslint-plugin-sf-plugin@^1.14.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-sf-plugin/-/eslint-plugin-sf-plugin-1.14.0.tgz#6bb25bd107119019e854595249b0c792aac5c3d4" + integrity sha512-KMgHn0uhml3ZjirCIP6h3e8PtIlN0JnTTOwypq17HJvOvKkb7SDPzCn4ogk/LfOGa0WrTuMGSzRWbrM3lhNydQ== + dependencies: + "@salesforce/core" "^3.33.6" + "@typescript-eslint/utils" "^5.54.1" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3606,20 +3611,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -fancy-test@^2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/fancy-test/-/fancy-test-2.0.12.tgz#a93cd92ffc23f70b069c39f19940d34f64c6ca67" - integrity sha512-S7qVQNaViLTMzn71huZvrUCV59ldq+enQ1EQOkdNbl4q4Om97gwqbYKvZoglsnzCWRRFaFP+qHynpdqaLdiZqg== - dependencies: - "@types/chai" "*" - "@types/lodash" "*" - "@types/node" "*" - "@types/sinon" "*" - lodash "^4.17.13" - mock-stdin "^1.0.0" - nock "^13.3.0" - stdout-stderr "^0.1.9" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3823,6 +3814,15 @@ fs-constants@^1.0.0: resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra@^10.0.1: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" @@ -4139,12 +4139,7 @@ got@^11, got@^11.8.2, got@^11.8.6: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6: - version "4.2.10" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -graceful-fs@^4.2.11: +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -4164,9 +4159,9 @@ growl@1.10.5: resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@4.7.7: +handlebars@^4.7.7: version "4.7.7" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== dependencies: minimist "^1.2.5" @@ -4982,11 +4977,6 @@ json-stringify-nice@^1.1.4: resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - json5@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -5221,7 +5211,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5648,11 +5638,6 @@ mocha@^9.1.3: yargs-parser "20.2.4" yargs-unparser "2.0.0" -mock-stdin@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/mock-stdin/-/mock-stdin-1.0.0.tgz#efcfaf4b18077e14541742fd758b9cae4e5365ea" - integrity sha512-tukRdb9Beu27t6dN+XztSRHq9J0B/CoAOySGzHfn8UTfmqipA5yNT/sDUEyYdAV3Hpka6Wx6kOMxuObdOex60Q== - mri@^1.1.5: version "1.2.0" resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -5808,16 +5793,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -nock@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.3.0.tgz#b13069c1a03f1ad63120f994b04bfd2556925768" - integrity sha512-HHqYQ6mBeiMc+N038w8LkMpDCRquCHWeNmN3v6645P3NhN2+qXOBqvPqo7Rt1VyCMzKhJ733wZqw5B7cQVFNPg== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.21" - propagate "^2.0.0" - node-emoji@^1.10.0: version "1.11.0" resolved "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -6532,11 +6507,6 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== - proper-lockfile@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" @@ -6761,7 +6731,7 @@ regexp.prototype.flags@^1.4.3: regexpp@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== regextras@^0.8.0: @@ -7291,14 +7261,6 @@ statuses@2.0.1: resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stdout-stderr@^0.1.9: - version "0.1.13" - resolved "https://registry.npmjs.org/stdout-stderr/-/stdout-stderr-0.1.13.tgz#54e3450f3d4c54086a49c0c7f8786a44d1844b6f" - integrity sha512-Xnt9/HHHYfjZ7NeQLvuQDyL1LnbsbddgMFKCuaQKwGCdJm8LnstZIXop+uOY36UR1UXXoHXfMbC1KlVdVd2JLA== - dependencies: - debug "^4.1.1" - strip-ansi "^6.0.0" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"