diff --git a/.github/workflows/create-github-release.yml b/.github/workflows/create-github-release.yml index a03dbf6e..2021e825 100644 --- a/.github/workflows/create-github-release.yml +++ b/.github/workflows/create-github-release.yml @@ -6,12 +6,12 @@ on: - main - prerelease/** tags-ignore: - - "*" + - '*' workflow_dispatch: inputs: prerelease: type: string - description: "Name to use for the prerelease: beta, dev, etc. NOTE: If this is already set in the package.json, it does not need to be passed in here." + description: 'Name to use for the prerelease: beta, dev, etc. NOTE: If this is already set in the package.json, it does not need to be passed in here.' jobs: release: diff --git a/.github/workflows/manualRelease.yml b/.github/workflows/manualRelease.yml new file mode 100644 index 00000000..8ceb52c3 --- /dev/null +++ b/.github/workflows/manualRelease.yml @@ -0,0 +1,36 @@ +name: manual release + +on: + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + - name: Conventional Changelog Action + id: changelog + uses: TriPSs/conventional-changelog-action@d360fad3a42feca6462f72c97c165d60a02d4bf2 + # overriding some of the basic behaviors to just get the changelog + with: + git-user-name: svc-cli-bot + git-user-email: svc_cli_bot@salesforce.com + github-token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + output-file: false + # always do the release, even if there are no semantic commits + skip-on-empty: false + tag-prefix: '' + - uses: notiz-dev/github-action-json-property@2192e246737701f108a4571462b76c75e7376216 + id: packageVersion + with: + path: 'package.json' + prop_path: 'version' + - name: Create Github Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + with: + tag_name: ${{ steps.packageVersion.outputs.prop }} + release_name: ${{ steps.packageVersion.outputs.prop }} diff --git a/.github/workflows/onPushToMain.yml b/.github/workflows/onPushToMain.yml new file mode 100644 index 00000000..b00f1cb7 --- /dev/null +++ b/.github/workflows/onPushToMain.yml @@ -0,0 +1,18 @@ +# test +name: version, tag and github release + +on: + push: + branches: [main] + +jobs: + release: + uses: salesforcecli/github-workflows/.github/workflows/githubRelease.yml@main + secrets: inherit + + # most repos won't use this + # depends on previous job to avoid git collisions, not for any functionality reason + # docs: + # uses: salesforcecli/github-workflows/.github/workflows/publishTypedoc.yml@main + # secrets: inherit + # needs: release diff --git a/CHANGELOG.md b/CHANGELOG.md index 47fdd14e..e0c5ef5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,398 +1,247 @@ -# [1.3.0](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.52...1.3.0) (2023-11-15) - - -### Features - -* **salesforcecli:** add new workflow to support pre release ([fffc9f9](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/fffc9f958fa4921a232ceb26871bd0a026269562)) - - - -## [1.2.52](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.51...1.2.52) (2023-11-12) - - -### Bug Fixes - -* **deps:** bump @types/lodash.chunk from 4.2.8 to 4.2.9 ([5328b3a](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5328b3aa7c6164df0bab54235dc17295861994b7)) - - - ## [1.2.51](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.50...1.2.51) (2023-10-29) - ### Bug Fixes -* **deps:** bump @types/lodash.chunk from 4.2.7 to 4.2.8 ([0b327c1](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/0b327c1577ddcbf224ccb1796f6900b4b38865c6)) - - +- **deps:** bump @types/lodash.chunk from 4.2.7 to 4.2.8 ([0b327c1](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/0b327c1577ddcbf224ccb1796f6900b4b38865c6)) ## [1.2.50](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.49...1.2.50) (2023-10-18) - ### Bug Fixes -* **deps:** bump @babel/traverse from 7.17.3 to 7.23.2 ([b5cc633](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b5cc633d33a315ba2da76384f6f742d604015abd)) - - +- **deps:** bump @babel/traverse from 7.17.3 to 7.23.2 ([b5cc633](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b5cc633d33a315ba2da76384f6f742d604015abd)) ## [1.2.49](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.48...1.2.49) (2023-09-28) - ### Bug Fixes -* **deps:** bump get-func-name from 2.0.0 to 2.0.2 ([d62af2a](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d62af2acd40f1c0eb1be9ad8503912a6e49ffc79)) - - +- **deps:** bump get-func-name from 2.0.0 to 2.0.2 ([d62af2a](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d62af2acd40f1c0eb1be9ad8503912a6e49ffc79)) ## [1.2.48](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.47...1.2.48) (2023-08-27) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.16 to 1.18.17 ([4d5f999](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/4d5f99909606d155fb18f52c8f3d1e7e73a0409e)) - - +- **deps:** bump @oclif/config from 1.18.16 to 1.18.17 ([4d5f999](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/4d5f99909606d155fb18f52c8f3d1e7e73a0409e)) ## [1.2.47](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.46...1.2.47) (2023-08-20) - ### Bug Fixes -* **deps:** bump tslib from 2.6.1 to 2.6.2 ([bfee66f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/bfee66f2e05c25f64c4b1a4dcb820101219d6940)) - - +- **deps:** bump tslib from 2.6.1 to 2.6.2 ([bfee66f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/bfee66f2e05c25f64c4b1a4dcb820101219d6940)) ## [1.2.46](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.45...1.2.46) (2023-08-06) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.15 to 1.18.16 ([b0a22d0](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b0a22d08371ab785d7ec36143cf228b78d607348)) - - +- **deps:** bump @oclif/config from 1.18.15 to 1.18.16 ([b0a22d0](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b0a22d08371ab785d7ec36143cf228b78d607348)) ## [1.2.45](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.44...1.2.45) (2023-07-30) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.14 to 1.18.15 ([a24bc28](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/a24bc280cd9307ee0a4c7d4176fb44dd4d3cb611)) - - +- **deps:** bump @oclif/config from 1.18.14 to 1.18.15 ([a24bc28](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/a24bc280cd9307ee0a4c7d4176fb44dd4d3cb611)) ## [1.2.44](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.43...1.2.44) (2023-07-30) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.34 to 1.8.35 ([2adf7f3](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/2adf7f34ec4d49c2486b1bb6af1a64536d849ed4)) - - +- **deps:** bump @oclif/command from 1.8.34 to 1.8.35 ([2adf7f3](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/2adf7f34ec4d49c2486b1bb6af1a64536d849ed4)) ## [1.2.43](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.42...1.2.43) (2023-07-23) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.32 to 1.8.34 ([561f140](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/561f140ee5f031b3eef13f38700f5bfd440670aa)) - - +- **deps:** bump @oclif/command from 1.8.32 to 1.8.34 ([561f140](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/561f140ee5f031b3eef13f38700f5bfd440670aa)) ## [1.2.42](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.41...1.2.42) (2023-07-23) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.13 to 1.18.14 ([420f19d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/420f19dda1489b8fd3b965d85411fd260a1fa09c)) - - +- **deps:** bump @oclif/config from 1.18.13 to 1.18.14 ([420f19d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/420f19dda1489b8fd3b965d85411fd260a1fa09c)) ## [1.2.41](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.40...1.2.41) (2023-07-20) - ### Bug Fixes -* **deps:** bump word-wrap from 1.2.3 to 1.2.4 ([b6271fe](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b6271fe43ce161cfb06b333c95fa2e31041b78d1)) - - +- **deps:** bump word-wrap from 1.2.3 to 1.2.4 ([b6271fe](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/b6271fe43ce161cfb06b333c95fa2e31041b78d1)) ## [1.2.40](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.39...1.2.40) (2023-07-16) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.11 to 1.18.13 ([e41f19f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e41f19f59056859c973dc210e538896f2edf5093)) - - +- **deps:** bump @oclif/config from 1.18.11 to 1.18.13 ([e41f19f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e41f19f59056859c973dc210e538896f2edf5093)) ## [1.2.39](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.38...1.2.39) (2023-07-16) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.31 to 1.8.32 ([5bc702d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5bc702deb03a6a68fe88338083aa8be91b185931)) - - +- **deps:** bump @oclif/command from 1.8.31 to 1.8.32 ([5bc702d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5bc702deb03a6a68fe88338083aa8be91b185931)) ## [1.2.38](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.37...1.2.38) (2023-07-12) - ### Bug Fixes -* **deps:** bump semver from 5.7.1 to 5.7.2 ([d8d8e9c](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d8d8e9c49ee2cf2bf47796d207b7ea5b895265ef)) - - +- **deps:** bump semver from 5.7.1 to 5.7.2 ([d8d8e9c](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d8d8e9c49ee2cf2bf47796d207b7ea5b895265ef)) ## [1.2.37](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.36...1.2.37) (2023-07-09) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.29 to 1.8.31 ([ea1ea7f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/ea1ea7fa4c80b946f5d2d88fbeda4b6a2e8b64d1)) - - +- **deps:** bump @oclif/command from 1.8.29 to 1.8.31 ([ea1ea7f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/ea1ea7fa4c80b946f5d2d88fbeda4b6a2e8b64d1)) ## [1.2.36](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.35...1.2.36) (2023-07-09) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.10 to 1.18.11 ([9d2a6c0](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/9d2a6c00ecf3d0da464195eb3d6b68f372dae7e3)) - - +- **deps:** bump @oclif/config from 1.18.10 to 1.18.11 ([9d2a6c0](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/9d2a6c00ecf3d0da464195eb3d6b68f372dae7e3)) ## [1.2.35](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.34...1.2.35) (2023-07-02) - ### Bug Fixes -* **deps:** bump tslib from 2.5.3 to 2.6.0 ([4b03cb7](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/4b03cb796a7961373b4fed9b6335e24b1cfdb758)) - - +- **deps:** bump tslib from 2.5.3 to 2.6.0 ([4b03cb7](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/4b03cb796a7961373b4fed9b6335e24b1cfdb758)) ## [1.2.34](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.33...1.2.34) (2023-06-25) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.28 to 1.8.29 ([ef6726f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/ef6726ffbacb3009329ea517f9d7729886406473)) - - +- **deps:** bump @oclif/command from 1.8.28 to 1.8.29 ([ef6726f](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/ef6726ffbacb3009329ea517f9d7729886406473)) ## [1.2.33](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.32...1.2.33) (2023-06-18) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.27 to 1.8.28 ([eeb0caf](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/eeb0cafe917d44db809873a9f0b32d2d2395fa73)) - - +- **deps:** bump @oclif/command from 1.8.27 to 1.8.28 ([eeb0caf](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/eeb0cafe917d44db809873a9f0b32d2d2395fa73)) ## [1.2.32](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.31...1.2.32) (2023-06-11) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.9 to 1.18.10 ([086bc21](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/086bc212490d68a656e158eadb8315f0f76fd2ce)) - - +- **deps:** bump @oclif/config from 1.18.9 to 1.18.10 ([086bc21](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/086bc212490d68a656e158eadb8315f0f76fd2ce)) ## [1.2.31](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.30...1.2.31) (2023-06-04) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.26 to 1.8.27 ([9daf594](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/9daf5946a1282b8d05d5e543235d8850e5338e15)) - - +- **deps:** bump @oclif/command from 1.8.26 to 1.8.27 ([9daf594](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/9daf5946a1282b8d05d5e543235d8850e5338e15)) ## [1.2.30](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.29...1.2.30) (2023-06-04) - ### Bug Fixes -* **deps:** bump tslib from 2.5.2 to 2.5.3 ([3328455](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/33284558b451e2fc7b57077b2f72d143a0f93e4b)) - - +- **deps:** bump tslib from 2.5.2 to 2.5.3 ([3328455](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/33284558b451e2fc7b57077b2f72d143a0f93e4b)) ## [1.2.29](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.28...1.2.29) (2023-05-28) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.8 to 1.18.9 ([f2f1974](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/f2f1974dd1fdfb712a31b1ee7476490c5ffa1432)) - - +- **deps:** bump @oclif/config from 1.18.8 to 1.18.9 ([f2f1974](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/f2f1974dd1fdfb712a31b1ee7476490c5ffa1432)) ## [1.2.28](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.27...1.2.28) (2023-05-21) - ### Bug Fixes -* **deps:** bump tslib from 2.5.0 to 2.5.2 ([bb56bfa](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/bb56bfafef31e83f6b655078e8fc99fdc9eb95d2)) - - +- **deps:** bump tslib from 2.5.0 to 2.5.2 ([bb56bfa](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/bb56bfafef31e83f6b655078e8fc99fdc9eb95d2)) ## [1.2.27](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.26...1.2.27) (2023-05-21) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.25 to 1.8.26 ([250126a](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/250126a5cc8318841461d58368f14d3972a72fef)) - - +- **deps:** bump @oclif/command from 1.8.25 to 1.8.26 ([250126a](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/250126a5cc8318841461d58368f14d3972a72fef)) ## [1.2.26](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.25...1.2.26) (2023-05-14) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.24 to 1.8.25 ([1d9a6fb](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/1d9a6fb39fe73158ef62c0d3c665758b2dcd7a96)) - - +- **deps:** bump @oclif/command from 1.8.24 to 1.8.25 ([1d9a6fb](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/1d9a6fb39fe73158ef62c0d3c665758b2dcd7a96)) ## [1.2.25](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.24...1.2.25) (2023-04-23) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.23 to 1.8.24 ([d5d30aa](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d5d30aa1271bacc6f7996d49bc020f9ec5fe481c)) - - +- **deps:** bump @oclif/command from 1.8.23 to 1.8.24 ([d5d30aa](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/d5d30aa1271bacc6f7996d49bc020f9ec5fe481c)) ## [1.2.24](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.23...1.2.24) (2023-04-16) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.22 to 1.8.23 ([e2f3830](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e2f3830a936216681a80ead68a0675d5b940adc0)) - - +- **deps:** bump @oclif/command from 1.8.22 to 1.8.23 ([e2f3830](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e2f3830a936216681a80ead68a0675d5b940adc0)) ## [1.2.23](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.22...1.2.23) (2023-02-26) - ### Bug Fixes -* **deps:** bump open from 8.4.1 to 8.4.2 ([7886860](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/78868602840092c6368d6bdbc5837eaddf502272)) - - +- **deps:** bump open from 8.4.1 to 8.4.2 ([7886860](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/78868602840092c6368d6bdbc5837eaddf502272)) ## [1.2.22](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.21...1.2.22) (2023-02-12) - ### Bug Fixes -* **deps:** bump open from 8.4.0 to 8.4.1 ([15d09dd](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/15d09ddbc0891cf48e4ba57f9e64ec4232e73c9a)) - - +- **deps:** bump open from 8.4.0 to 8.4.1 ([15d09dd](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/15d09ddbc0891cf48e4ba57f9e64ec4232e73c9a)) ## [1.2.21](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.20...1.2.21) (2023-02-05) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.6 to 1.18.8 ([7bb67ec](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/7bb67ecfaaa3da8323168ca3cf25e254e8057f52)) - - +- **deps:** bump @oclif/config from 1.18.6 to 1.18.8 ([7bb67ec](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/7bb67ecfaaa3da8323168ca3cf25e254e8057f52)) ## [1.2.20](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.19...1.2.20) (2023-01-29) - ### Bug Fixes -* **deps:** bump tslib from 2.4.1 to 2.5.0 ([5f2238d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5f2238d26c4710f6e2dcf09e44e8607ef1883542)) - - +- **deps:** bump tslib from 2.4.1 to 2.5.0 ([5f2238d](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5f2238d26c4710f6e2dcf09e44e8607ef1883542)) ## [1.2.19](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.18...1.2.19) (2023-01-29) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.21 to 1.8.22 ([5c63a65](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5c63a6599534aed7aaa10b2ae8a0b8cdf2612dc7)) - - +- **deps:** bump @oclif/command from 1.8.21 to 1.8.22 ([5c63a65](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/5c63a6599534aed7aaa10b2ae8a0b8cdf2612dc7)) ## [1.2.18](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.17...1.2.18) (2023-01-15) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.19 to 1.8.21 ([076533b](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/076533bbb020a637e8610276acc786904cdc645c)) - - +- **deps:** bump @oclif/command from 1.8.19 to 1.8.21 ([076533b](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/076533bbb020a637e8610276acc786904cdc645c)) ## [1.2.17](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.16...1.2.17) (2023-01-08) - ### Bug Fixes -* **deps:** bump json5 from 1.0.1 to 1.0.2 ([a971220](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/a9712207ea5c895a6d821072ad73d145c35579f8)) - - +- **deps:** bump json5 from 1.0.1 to 1.0.2 ([a971220](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/a9712207ea5c895a6d821072ad73d145c35579f8)) ## [1.2.16](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.15...1.2.16) (2022-11-13) - ### Bug Fixes -* **deps:** bump @oclif/config from 1.18.5 to 1.18.6 ([e3883d2](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e3883d291aaeb53189a50d56db967f9cffabe5b8)) - - +- **deps:** bump @oclif/config from 1.18.5 to 1.18.6 ([e3883d2](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/e3883d291aaeb53189a50d56db967f9cffabe5b8)) ## [1.2.15](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.14...1.2.15) (2022-11-09) - - ## [1.2.14](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.13...1.2.14) (2022-11-01) - - ## [1.2.13](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.12...1.2.13) (2022-11-01) - - ## [1.2.12](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/1.2.11...1.2.12) (2022-10-30) - ### Bug Fixes -* **deps:** bump @oclif/command from 1.8.18 to 1.8.19 ([feb3066](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/feb3066446d6c2ad2596a69dec8f3a2a3d23136c)) - - +- **deps:** bump @oclif/command from 1.8.18 to 1.8.19 ([feb3066](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/feb3066446d6c2ad2596a69dec8f3a2a3d23136c)) ## [1.2.11](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.7-beta.1...1.2.11) (2022-10-20) - ### Bug Fixes -* bump npm version ([6b9c8a9](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/6b9c8a930858dee9587c491fefafbfc8b9e3e2db)) -* **deps:** bump @oclif/command from 1.8.16 to 1.8.18 ([c33e011](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/c33e0115637a433a0dcb641776b3f2ff3a457150)) -* **deps:** bump @oclif/config from 1.18.3 to 1.18.5 ([01499f4](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/01499f4bd2045daae11296a094aa14c521bbbc57)) - - +- bump npm version ([6b9c8a9](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/6b9c8a930858dee9587c491fefafbfc8b9e3e2db)) +- **deps:** bump @oclif/command from 1.8.16 to 1.8.18 ([c33e011](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/c33e0115637a433a0dcb641776b3f2ff3a457150)) +- **deps:** bump @oclif/config from 1.18.3 to 1.18.5 ([01499f4](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/commit/01499f4bd2045daae11296a094aa14c521bbbc57)) ## [1.2.7-beta.1](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.6...v1.2.7-beta.1) (2022-09-26) - - ## [1.2.6](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.5...v1.2.6) (2022-06-23) - - ## [1.2.5](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.4...v1.2.5) (2022-06-20) - - ## [1.2.4](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.3...v1.2.4) (2022-06-14) - - ## [1.2.3](https://github.com/salesforcecli/plugin-omnistudio-migration-tool/compare/v1.2.2...v1.2.3) (2022-06-14) - - ## 1.2.2 (2022-06-13) - - - diff --git a/DEV.md b/DEV.md index daa8f3c0..6c2d37f0 100644 --- a/DEV.md +++ b/DEV.md @@ -1,5 +1,4 @@ -OmniStudio Migration Tool -========================= +# OmniStudio Migration Tool This repository contains the code required to enable the OmniStudio Migration Tool SFDX plugin. @@ -9,7 +8,8 @@ This repository contains the code required to enable the OmniStudio Migration To 2. Authenticate your SFDX cli into the org you are going to use for development. You can follow authentication steps [here](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_auth_web.htm). 3. Clone this repository into your local machine. 4. Open the migration tool code folder in VSCode or your prefered editor. -5. In a new command line tool, run the following command: +5. In a new command line tool, run the following command: + ``` bin/run omnistudio:migration:migrate -u agarcia-vertical238@na46.salesforce.com --namespace=agarciana46_238 --json ``` @@ -18,7 +18,7 @@ bin/run omnistudio:migration:migrate -u agarcia-vertical238@na46.salesforce.com ``` USAGE - $ sfdx omnistudio:migration:migrate [-n ] [-f] [-v ] [-u ] [--apiversion ] [--json] [--loglevel + $ sfdx omnistudio:migration:migrate [-n ] [-f] [-v ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL] OPTIONS @@ -38,11 +38,14 @@ OPTIONS --loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for this command invocation + -a, --allversions migrate all versions + ``` ### Folder structure + ``` -- +- - .vscode VSCode configuration folder - bin Tools required to run in developer mode - messages JSON files with user messages used in the plugin @@ -53,23 +56,27 @@ OPTIONS - utils Utilities (network, debugging, logging, etc.) ``` - - _See code: [src/commands/hello/org.ts](https://github.com/agarcia-sf/omnistudio-migration-tool/blob/v0.0.0/src/commands/hello/org.ts)_ + + # Debugging your plugin + We recommend using the Visual Studio Code (VS Code) IDE for your plugin development. Included in the `.vscode` directory of this plugin is a `launch.json` config file, which allows you to attach a debugger to the node process when running your commands. -To debug the `hello:org` command: +To debug the `hello:org` command: + 1. Start the inspector - -If you linked your plugin to the sfdx cli, call your command with the `dev-suspend` switch: + +If you linked your plugin to the sfdx cli, call your command with the `dev-suspend` switch: + ```sh-session $ sfdx hello:org -u myOrg@example.com --dev-suspend ``` - + Alternatively, to call your command using the `bin/run` script, set the `NODE_OPTIONS` environment variable to `--inspect-brk` when starting the debugger: + ```sh-session $ NODE_OPTIONS=--inspect-brk bin/run hello:org -u myOrg@example.com ``` @@ -77,7 +84,7 @@ $ NODE_OPTIONS=--inspect-brk bin/run hello:org -u myOrg@example.com 2. Set some breakpoints in your command code 3. Click on the Debug icon in the Activity Bar on the side of VS Code to open up the Debug view. 4. In the upper left hand corner of VS Code, verify that the "Attach to Remote" launch configuration has been chosen. -5. Hit the green play button to the left of the "Attach to Remote" launch configuration window. The debugger should now be suspended on the first line of the program. +5. Hit the green play button to the left of the "Attach to Remote" launch configuration window. The debugger should now be suspended on the first line of the program. 6. Hit the green play button at the top middle of VS Code (this play button will be to the right of the play button that you clicked in step #5). -

-Congrats, you are debugging! \ No newline at end of file +

+ Congrats, you are debugging! diff --git a/README.md b/README.md index 0a60fe89..6376489e 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,21 @@ -OmniStudio Migration Tool -========================= - +# OmniStudio Migration Tool ### Before You Begin -1. Confirm you have an OmniStudio Admin license. -2. Enable Standard OmniStudio Runtime in Setup > OmniStudio Settings. + +Read and follow the directions in the Omnistudio migration documentation: https://help.salesforce.com/s/articleView?id=sf.os_migrate_omnistudio_custom_objects_to_standard_objects.htm&type=5 ## Running SFDX plugin 1. Install SFDX cli using the official documentation located [here](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_install_cli.htm). 2. Authenticate your SFDX cli into the org you are going to use for development. You can follow authentication steps [here](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_auth_web.htm). 3. In a new terminal session, install the plugin using the following command + ``` sfdx plugins:install @salesforce/plugin-omnistudio-migration-tool ``` + 4. To run the migration tool, run the following command from your command line tool: + ``` // To migrate everything sfdx omnistudio:migration:migrate -u YOUR_ORG_USERNAME@DOMAIN.COM --namespace=VLOCITY_PACKAGE_NAMESPACE @@ -24,18 +25,23 @@ sfdx omnistudio:migration:migrate -u YOUR_ORG_USERNAME@DOMAIN.COM --namespace=VL --only=ip --only=os --only=fc + +//to migrate all versions of the components and not just the active ones: +--allversions ``` + 5. An HTML page will be open in your default browser with the results of your migration job. ### Usage & parameters ``` USAGE - $ sfdx omnistudio:migration:migrate [-n ] [-f] [-v ] [-u ] [--apiversion ] [--json] [--loglevel + $ sfdx omnistudio:migration:migrate [-n ] [-f] [-v ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL] OPTIONS -n, --namespace=namespace the namespace of the vertical package + -n, --namespace=namespace the namespace of the vertical package -u, --targetusername=targetusername username or alias for the target org; overrides default target org @@ -51,4 +57,7 @@ OPTIONS --loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for this command invocation + -a, --allversions migrate all versions and not + and not just the active ones. + ``` diff --git a/command-snapshot.json b/command-snapshot.json index 685fc15c..8a7d94ad 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -2,38 +2,19 @@ { "command": "basecommand", "plugin": "@salesforce/plugin-omnistudio-migration-tool", - "flags": [ - "apiversion", - "json", - "loglevel", - "targetusername" - ], + "flags": ["apiversion", "json", "loglevel", "targetusername"], "alias": [] }, { "command": "omnistudio:migration:info", "plugin": "@salesforce/plugin-omnistudio-migration-tool", - "flags": [ - "apiversion", - "json", - "loglevel", - "name", - "targetdevhubusername", - "targetusername" - ], + "flags": ["allversions", "apiversion", "json", "loglevel", "name", "targetdevhubusername", "targetusername"], "alias": [] }, { "command": "omnistudio:migration:migrate", "plugin": "@salesforce/plugin-omnistudio-migration-tool", - "flags": [ - "apiversion", - "json", - "loglevel", - "namespace", - "only", - "targetusername" - ], + "flags": ["allversions", "apiversion", "json", "loglevel", "namespace", "only", "targetusername"], "alias": [] } -] \ No newline at end of file +] diff --git a/messages/info.json b/messages/info.json index 69b5e1cf..86b72caa 100644 --- a/messages/info.json +++ b/messages/info.json @@ -6,5 +6,6 @@ "examples": [ "sfdx omnistudio:migration:info --targetusername myOrg@example.com --targetdevhubusername devhub@org.com", "sfdx omnistudio:migration:info --name myname --targetusername myOrg@example.com" - ] -} \ No newline at end of file + ], + "allVersionsDescription": "Migrate all versions of a component" +} diff --git a/messages/migrate.json b/messages/migrate.json index f3c8e782..7a51a4c9 100644 --- a/messages/migrate.json +++ b/messages/migrate.json @@ -24,5 +24,6 @@ "errorWhileActivatingOs": "Could not activate OmniScript / Integration Procedure: ", "errorWhileActivatingCard": "Could not activate Card: ", "errorWhileUploadingCard": "An error ocurred while uploading Card: ", - "errorWhileCreatingElements": "An error ocurred while saving OmniScript elements: " -} \ No newline at end of file + "errorWhileCreatingElements": "An error ocurred while saving OmniScript elements: ", + "allVersionsDescription": "Migrate all versions of a component" +} diff --git a/package.json b/package.json index b585ad04..24405095 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@salesforce/plugin-omnistudio-migration-tool", "description": "This SFDX plugin migrates FlexCard, OmniScript, DataRaptor, and Integration Procedure custom objects to standard objects.", - "version": "1.3.0", + "version": "1.2.52-beta.0", "author": "Salesforce", "bugs": "https://github.com/forcedotcom/cli/issues", "dependencies": { diff --git a/src/commands/omnistudio/migration/info.ts b/src/commands/omnistudio/migration/info.ts index f062a311..416637a9 100644 --- a/src/commands/omnistudio/migration/info.ts +++ b/src/commands/omnistudio/migration/info.ts @@ -29,6 +29,11 @@ export default class Org extends SfdxCommand { char: 'n', description: messages.getMessage('nameFlagDescription'), }), + allversions: flags.boolean({ + char: 'a', + description: messages.getMessage('allVersionsDescription'), + required: false, + }), }; // Comment this out if your command does not require an org username @@ -42,6 +47,8 @@ export default class Org extends SfdxCommand { public async run(): Promise { const name = (this.flags.name || 'world') as string; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const allVersions = this.flags.allversions || false; // this.org is guaranteed because requiresUsername=true, as opposed to supportsUsername const conn = this.org.getConnection(); @@ -79,6 +86,10 @@ export default class Org extends SfdxCommand { this.ux.log(`My hub org id is: ${hubOrgId}`); } + if (allVersions) { + outputString = `${outputString} and all versions will be migrated`; + } + // Return an object to be displayed with --json return { orgId: this.org.getOrgId(), outputString }; } diff --git a/src/commands/omnistudio/migration/migrate.ts b/src/commands/omnistudio/migration/migrate.ts index eac8088e..2c0eafd1 100644 --- a/src/commands/omnistudio/migration/migrate.ts +++ b/src/commands/omnistudio/migration/migrate.ts @@ -42,6 +42,11 @@ export default class Migrate extends OmniStudioBaseCommand { char: 'o', description: messages.getMessage('onlyFlagDescription'), }), + allversions: flags.boolean({ + char: 'a', + description: messages.getMessage('allVersionsDescription'), + required: false, + }), }; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -49,6 +54,7 @@ export default class Migrate extends OmniStudioBaseCommand { const namespace = (this.flags.namespace || 'vlocity_ins') as string; const apiVersion = (this.flags.apiversion || '55.0') as string; const migrateOnly = (this.flags.only || '') as string; + const allVersions = this.flags.allversions || false; // this.org is guaranteed because requiresUsername=true, as opposed to supportsUsername const conn = this.org.getConnection(); @@ -62,23 +68,47 @@ export default class Migrate extends OmniStudioBaseCommand { if (!migrateOnly) { migrationObjects = [ new DataRaptorMigrationTool(namespace, conn, this.logger, messages, this.ux), - new OmniScriptMigrationTool(OmniScriptExportType.All, namespace, conn, this.logger, messages, this.ux), - new CardMigrationTool(namespace, conn, this.logger, messages, this.ux), + new OmniScriptMigrationTool( + OmniScriptExportType.All, + namespace, + conn, + this.logger, + messages, + this.ux, + allVersions + ), + new CardMigrationTool(namespace, conn, this.logger, messages, this.ux, allVersions), ]; } else { switch (migrateOnly) { case 'os': migrationObjects.push( - new OmniScriptMigrationTool(OmniScriptExportType.OS, namespace, conn, this.logger, messages, this.ux) + new OmniScriptMigrationTool( + OmniScriptExportType.OS, + namespace, + conn, + this.logger, + messages, + this.ux, + allVersions + ) ); break; case 'ip': migrationObjects.push( - new OmniScriptMigrationTool(OmniScriptExportType.IP, namespace, conn, this.logger, messages, this.ux) + new OmniScriptMigrationTool( + OmniScriptExportType.IP, + namespace, + conn, + this.logger, + messages, + this.ux, + allVersions + ) ); break; case 'fc': - migrationObjects.push(new CardMigrationTool(namespace, conn, this.logger, messages, this.ux)); + migrationObjects.push(new CardMigrationTool(namespace, conn, this.logger, messages, this.ux, allVersions)); break; case 'dr': migrationObjects.push(new DataRaptorMigrationTool(namespace, conn, this.logger, messages, this.ux)); diff --git a/src/migration/flexcard.ts b/src/migration/flexcard.ts index 54e645ae..eaeb0b85 100644 --- a/src/migration/flexcard.ts +++ b/src/migration/flexcard.ts @@ -1,371 +1,438 @@ /* eslint-disable */ import { AnyJson } from '@salesforce/ts-types'; import CardMappings from '../mappings/VlocityCard'; -import { DebugTimer, QueryTools } from '../utils'; +import { DebugTimer, QueryTools, SortDirection } from '../utils'; import { NetUtils } from '../utils/net'; import { BaseMigrationTool } from './base'; import { MigrationResult, MigrationTool, ObjectMapping, UploadRecordResult } from './interfaces'; +import { Connection, Logger, Messages } from '@salesforce/core'; +import { UX } from '@salesforce/command'; export class CardMigrationTool extends BaseMigrationTool implements MigrationTool { - - static readonly VLOCITYCARD_NAME = 'VlocityCard__c'; - static readonly OMNIUICARD_NAME = 'OmniUiCard'; - - getName(): string { - return "FlexCards"; - } - - getRecordName(record: string) { - return record['Name']; - } - - getMappings(): ObjectMapping[] { - return [{ - source: CardMigrationTool.VLOCITYCARD_NAME, - target: CardMigrationTool.OMNIUICARD_NAME - }]; - } - - // Perform Delete of OmniUiCard Records to start migration from scratch - async truncate(): Promise { - const objectName = CardMigrationTool.OMNIUICARD_NAME; - DebugTimer.getInstance().lap('Truncating ' + objectName); - - const ids: string[] = await QueryTools.queryIds(this.connection, objectName); - if (ids.length === 0) return; - - const recordsToUpdate = ids.map(id => { - return { - attributes: { type: CardMigrationTool.OMNIUICARD_NAME }, - Id: id, - IsActive: false - } - }); - - // Mark the OmniUiCards as inactive - await NetUtils.update(this.connection, recordsToUpdate); - - const success: boolean = await NetUtils.delete(this.connection, ids); - if (!success) { - throw new Error('Could not truncate ' + objectName); - } - } - - // Perform Records Migration from VlocityCard__c to OmniUiCard - async migrate(): Promise { - - // Get All the Active VlocityCard__c records - const cards = await this.getAllActiveCards(); - - // Save the Vlocity Cards in OmniUiCard - const cardUploadResponse = await this.uploadAllCards(cards); - - const records = new Map(); - for (let i = 0; i < cards.length; i++) { - records.set(cards[i]['Id'], cards[i]); - } - - return [{ - name: 'FlexCards', - records: records, - results: cardUploadResponse - }]; - } - - // Query all cards that are active - private async getAllActiveCards(): Promise { - DebugTimer.getInstance().lap('Query Vlocity Cards'); - // const filterStr: string = ` Where ${this.namespacePrefix}Active__c = true` - const filters = new Map(); - filters.set(this.namespacePrefix + 'Active__c', true); - filters.set(this.namespacePrefix + 'CardType__c', 'flex'); - - return await QueryTools.queryWithFilter(this.connection, this.namespace, CardMigrationTool.VLOCITYCARD_NAME, this.getCardFields(), filters); - } - - // Upload All the VlocityCard__c records to OmniUiCard - private async uploadAllCards(cards: any[]): Promise> { - - const cardsUploadInfo = new Map(); - const originalRecords = new Map(); - const uniqueNames = new Set(); - - for (let card of cards) { - await this.uploadCard(cards, card, cardsUploadInfo, originalRecords, uniqueNames); - } - - return cardsUploadInfo; - } - - private async uploadCard(allCards: any[], card: AnyJson, cardsUploadInfo: Map, originalRecords: Map, uniqueNames: Set) { - - const recordId = card['Id']; - - // If we already uploaded this card, skip - if (cardsUploadInfo.has(recordId)) { - return; - } - - try { - const childCards = this.getChildCards(card); - if (childCards.length > 0) { - for (let childCardName of childCards) { - // Upload child cards - const childCard = allCards.find(c => c['Name'] === childCardName); - if (childCard) { - await this.uploadCard(allCards, childCard, cardsUploadInfo, originalRecords, uniqueNames); - } - } - - this.updateChildCards(card); - } - - this.reportProgress(allCards.length, originalRecords.size); - - - // Perform the transformation - const invalidIpNames = new Map(); - const transformedCard = this.mapVlocityCardRecord(card, cardsUploadInfo, invalidIpNames); - - // Verify duplicated names - const transformedCardName = transformedCard['Name']; - const transformedCardAuthorName = transformedCard['AuthorName']; - if (uniqueNames.has(transformedCardName)) { - this.setRecordErrors(card, this.messages.getMessage('duplicatedCardName')); - originalRecords.set(recordId, card); - return; - } - - // Save the name for duplicated names check - uniqueNames.add(transformedCardName); - - // Create a map of the original records - originalRecords.set(recordId, card); - - // Create card - const uploadResult = await NetUtils.createOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, recordId, transformedCard); - - if (uploadResult) { - - // Fix errors - uploadResult.errors = uploadResult.errors || []; - if (!uploadResult.success) { - uploadResult.errors = Array.isArray(uploadResult.errors) ? uploadResult.errors : [uploadResult.errors]; - } - - // If name has been changed, add a warning message - uploadResult.warnings = uploadResult.warnings || []; - if (transformedCardAuthorName !== card[this.namespacePrefix + 'Author__c']) { - uploadResult.warnings.unshift('WARNING: Card author name has been modified to fit naming rules: ' + transformedCardAuthorName); - } - if (transformedCardName !== card['Name']) { - uploadResult.newName = transformedCardName; - uploadResult.warnings.unshift('WARNING: Card name has been modified to fit naming rules: ' + transformedCardName); - } - - if (uploadResult.id && invalidIpNames.size > 0) { - const val = Array.from(invalidIpNames.entries()).map(e => e[0]).join(', '); - uploadResult.errors.push('Integration Procedure Actions will need manual updates, please verify: ' + val); - } - - cardsUploadInfo.set(recordId, uploadResult); - const updateResult = await NetUtils.updateOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, recordId, uploadResult.id, { - [CardMappings.Active__c]: true - }); - - if (!updateResult.success) { - uploadResult.hasErrors = true; - uploadResult.errors = uploadResult.errors || []; - - uploadResult.errors.push(this.messages.getMessage('errorWhileActivatingCard') + updateResult.errors); - } - } - } catch (err) { - this.setRecordErrors(card, this.messages.getMessage('errorWhileUploadingCard') + err); - originalRecords.set(recordId, card); - - cardsUploadInfo.set(recordId, { - referenceId: recordId, - hasErrors: true, - success: false, - errors: err, - warnings: [] - }); - } - } - - private getChildCards(card: AnyJson): string[] { - let childs = []; - const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']); - if (!definition) return childs; - - for (let state of (definition.states || [])) { - if (state.childCards && Array.isArray(state.childCards)) { - childs = childs.concat(state.childCards); - - // Modify the name of the child cards - state.childCards = state.childCards.map(c => this.cleanName(c)); - } - } - - return childs; - } - - private updateChildCards(card: AnyJson): void { - const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']); - if (!definition) return; - - for (let state of (definition.states || [])) { - if (state.childCards && Array.isArray(state.childCards)) { - state.childCards = state.childCards.map(c => this.cleanName(c)); - } - } - - card[this.namespacePrefix + 'Definition__c'] = JSON.stringify(definition); - } - - // Maps an indivitdual VlocityCard__c record to an OmniUiCard record. - private mapVlocityCardRecord(cardRecord: AnyJson, cardsUploadInfo: Map, invalidIpNames: Map): AnyJson { - - // Transformed object - const mappedObject = {}; - - // Get the fields of the record - const recordFields = Object.keys(cardRecord); - - // Map individual fields - recordFields.forEach(recordField => { - const cleanFieldName = this.getCleanFieldName(recordField); - - if (CardMappings.hasOwnProperty(cleanFieldName) && cleanFieldName !== 'IsChildCard__c') { - mappedObject[CardMappings[cleanFieldName]] = cardRecord[recordField]; - - // Transform ParentId__c to ClonedFromOmniUiCardKey field from uploaded response map - if (cleanFieldName === "ParentID__c" && cardsUploadInfo.has(cardRecord[`${this.namespacePrefix}ParentID__c`])) { - mappedObject[CardMappings[cleanFieldName]] = cardsUploadInfo.get(cardRecord[`${this.namespacePrefix}ParentID__c`]).id; - } - - // CardType__c and OmniUiCardType have different picklist values - if (cleanFieldName === "CardType__c") { - let ischildCard = cardRecord[`${this.namespacePrefix}IsChildCard__c`]; - mappedObject["OmniUiCardType"] = ischildCard ? 'Child' : 'Parent'; - } - - // Child Cards don't have version, so assigning 1 - if (cleanFieldName === "Version__c") { - let versionNumber = cardRecord[`${this.namespacePrefix}Version__c`]; - mappedObject["VersionNumber"] = versionNumber ? versionNumber : 1; - } - } - }); - - // Clean the name - mappedObject['Name'] = this.cleanName(mappedObject['Name']); - mappedObject[CardMappings.Author__c] = this.cleanName(mappedObject[CardMappings.Author__c]); - mappedObject[CardMappings.Active__c] = false; - - // Update the datasource - const datasource = JSON.parse(mappedObject[CardMappings.Datasource__c] || '{}'); - if (datasource.dataSource) { - const type = datasource.dataSource.type; - if (type === 'DataRaptor') { - datasource.dataSource.value.bundle = this.cleanName(datasource.dataSource.value.bundle); - } else if (type === 'IntegrationProcedures') { - const ipMethod: string = datasource.dataSource.value.ipMethod || ''; - - const parts = ipMethod.split('_'); - const newKey = parts.map(p => this.cleanName(p, true)).join('_'); - - datasource.dataSource.value.ipMethod = newKey; - - if (parts.length > 2) { - invalidIpNames.set('DataSource', ipMethod); - } - } - mappedObject[CardMappings.Datasource__c] = JSON.stringify(datasource); - } - - // Update the propertyset datasource - const propertySet = JSON.parse(mappedObject[CardMappings.Definition__c] || '{}'); - if (propertySet) { - if (propertySet.dataSource) { - const type = propertySet.dataSource.type; - if (type === 'DataRaptor') { - propertySet.dataSource.value.bundle = this.cleanName(propertySet.dataSource.value.bundle); - } else if (type === 'IntegrationProcedures') { - const ipMethod: string = propertySet.dataSource.value.ipMethod || ''; - - const parts = ipMethod.split('_'); - const newKey = parts.map(p => this.cleanName(p, true)).join('_'); - propertySet.dataSource.value.ipMethod = newKey; - - if (parts.length > 2) { - invalidIpNames.set('DataSource', ipMethod); - } - } - } - - // update the states for child cards - for (let i = 0; i < (propertySet.states || []).length; i++) { - const state = propertySet.states[i]; - - // Clean childCards property - if (state.childCards && Array.isArray(state.childCards)) { - state.childCards = state.childCards.map(c => this.cleanName(c)); - } - - // Fix the "components" for child cards - for (let componentKey in state.components) { - if (state.components.hasOwnProperty(componentKey)) { - const component = state.components[componentKey]; - - if (component.children && Array.isArray(component.children)) { - this.fixChildren(component.children); - } - } - } - - if (state.omniscripts && Array.isArray(state.omniscripts)) { - for (let osIdx = 0; osIdx < state.omniscripts.length; osIdx++) { - state.omniscripts[osIdx].type = this.cleanName(state.omniscripts[osIdx].type); - state.omniscripts[osIdx].subtype = this.cleanName(state.omniscripts[osIdx].subtype); - } - } - } - - mappedObject[CardMappings.Definition__c] = JSON.stringify(propertySet); - } - - mappedObject['attributes'] = { - type: CardMigrationTool.OMNIUICARD_NAME, - referenceId: cardRecord['Id'] - }; - - return mappedObject; - } - - private fixChildren(children: any[]) { - for (let j = 0; j < children.length; j++) { - const child = children[j]; - - if (child.element === 'childCardPreview') { - child.property.cardName = this.cleanName(child.property.cardName); - } else if (child.element === 'action') { - - if (child.property && child.property.stateAction && child.property.stateAction.omniType) { - const parts = (child.property.stateAction.omniType.Name || '').split('/'); - child.property.stateAction.omniType.Name = parts.map(p => this.cleanName(p)).join('/'); - } - - } - - if (child.children && Array.isArray(child.children)) { - this.fixChildren(child.children); - } - } - } - - private getCardFields(): string[] { - return Object.keys(CardMappings); - } -} \ No newline at end of file + static readonly VLOCITYCARD_NAME = 'VlocityCard__c'; + static readonly OMNIUICARD_NAME = 'OmniUiCard'; + private readonly allVersions: boolean; + + constructor( + namespace: string, + connection: Connection, + logger: Logger, + messages: Messages, + ux: UX, + allVersions: boolean + ) { + super(namespace, connection, logger, messages, ux); + this.allVersions = allVersions; + } + + getName(): string { + return 'FlexCards'; + } + + getRecordName(record: string) { + return record['Name']; + } + + getMappings(): ObjectMapping[] { + return [ + { + source: CardMigrationTool.VLOCITYCARD_NAME, + target: CardMigrationTool.OMNIUICARD_NAME, + }, + ]; + } + + // Perform Delete of OmniUiCard Records to start migration from scratch + async truncate(): Promise { + const objectName = CardMigrationTool.OMNIUICARD_NAME; + DebugTimer.getInstance().lap('Truncating ' + objectName); + + const ids: string[] = await QueryTools.queryIds(this.connection, objectName); + if (ids.length === 0) return; + + const recordsToUpdate = ids.map((id) => { + return { + attributes: { type: CardMigrationTool.OMNIUICARD_NAME }, + Id: id, + IsActive: false, + }; + }); + + // Mark the OmniUiCards as inactive + await NetUtils.update(this.connection, recordsToUpdate); + + const success: boolean = await NetUtils.delete(this.connection, ids); + if (!success) { + throw new Error('Could not truncate ' + objectName); + } + } + + // Perform Records Migration from VlocityCard__c to OmniUiCard + async migrate(): Promise { + // Get All the Active VlocityCard__c records + const cards = await this.getAllActiveCards(); + + // Save the Vlocity Cards in OmniUiCard + const cardUploadResponse = await this.uploadAllCards(cards); + + const records = new Map(); + for (let i = 0; i < cards.length; i++) { + records.set(cards[i]['Id'], cards[i]); + } + + return [ + { + name: 'FlexCards', + records: records, + results: cardUploadResponse, + }, + ]; + } + + // Query all cards that are active + private async getAllActiveCards(): Promise { + DebugTimer.getInstance().lap('Query Vlocity Cards'); + const filters = new Map(); + filters.set(this.namespacePrefix + 'CardType__c', 'flex'); + + if (this.allVersions) { + const sortFields = [ + { field: 'Name', direction: SortDirection.ASC }, + { field: this.namespacePrefix + 'Version__c', direction: SortDirection.ASC }, + ]; + return await QueryTools.queryWithFilterAndSort( + this.connection, + this.namespace, + CardMigrationTool.VLOCITYCARD_NAME, + this.getCardFields(), + filters, + sortFields + ); + } else { + filters.set(this.namespacePrefix + 'Active__c', true); + return await QueryTools.queryWithFilter( + this.connection, + this.namespace, + CardMigrationTool.VLOCITYCARD_NAME, + this.getCardFields(), + filters + ); + } + } + + // Upload All the VlocityCard__c records to OmniUiCard + private async uploadAllCards(cards: any[]): Promise> { + const cardsUploadInfo = new Map(); + const originalRecords = new Map(); + const uniqueNames = new Set(); + + for (let card of cards) { + await this.uploadCard(cards, card, cardsUploadInfo, originalRecords, uniqueNames); + } + + return cardsUploadInfo; + } + + private async uploadCard( + allCards: any[], + card: AnyJson, + cardsUploadInfo: Map, + originalRecords: Map, + uniqueNames: Set + ) { + const recordId = card['Id']; + + // If we already uploaded this card, skip + if (cardsUploadInfo.has(recordId)) { + return; + } + const isCardActive = card[`${this.namespacePrefix}Active__c`]; + + try { + const childCards = this.getChildCards(card); + if (childCards.length > 0) { + for (let childCardName of childCards) { + // Upload child cards + const childCard = allCards.find((c) => c['Name'] === childCardName); + if (childCard) { + await this.uploadCard(allCards, childCard, cardsUploadInfo, originalRecords, uniqueNames); + } + } + + this.updateChildCards(card); + } + + this.reportProgress(allCards.length, originalRecords.size); + + // Perform the transformation + const invalidIpNames = new Map(); + const transformedCard = this.mapVlocityCardRecord(card, cardsUploadInfo, invalidIpNames); + + // Verify duplicated names + let transformedCardName: string; + if (this.allVersions) { + transformedCardName = transformedCard['Name'] + '_' + transformedCard['VersionNumber']; + } else { + transformedCardName = transformedCard['Name']; + } + const transformedCardAuthorName = transformedCard['AuthorName']; + + if (uniqueNames.has(transformedCardName)) { + this.setRecordErrors(card, this.messages.getMessage('duplicatedCardName')); + originalRecords.set(recordId, card); + return; + } + + // Save the name for duplicated names check + uniqueNames.add(transformedCardName); + + // Create a map of the original records + originalRecords.set(recordId, card); + + // Create card + const uploadResult = await NetUtils.createOne( + this.connection, + CardMigrationTool.OMNIUICARD_NAME, + recordId, + transformedCard + ); + + if (uploadResult) { + // Fix errors + uploadResult.errors = uploadResult.errors || []; + if (!uploadResult.success) { + uploadResult.errors = Array.isArray(uploadResult.errors) ? uploadResult.errors : [uploadResult.errors]; + } + + // If name has been changed, add a warning message + uploadResult.warnings = uploadResult.warnings || []; + if (transformedCardAuthorName !== card[this.namespacePrefix + 'Author__c']) { + uploadResult.warnings.unshift( + 'WARNING: Card author name has been modified to fit naming rules: ' + transformedCardAuthorName + ); + } + if (transformedCardName !== card['Name']) { + uploadResult.newName = transformedCardName; + uploadResult.warnings.unshift( + 'WARNING: Card name has been modified to fit naming rules: ' + transformedCardName + ); + } + + if (uploadResult.id && invalidIpNames.size > 0) { + const val = Array.from(invalidIpNames.entries()) + .map((e) => e[0]) + .join(', '); + uploadResult.errors.push('Integration Procedure Actions will need manual updates, please verify: ' + val); + } + + cardsUploadInfo.set(recordId, uploadResult); + + const updateResult = await NetUtils.updateOne( + this.connection, + CardMigrationTool.OMNIUICARD_NAME, + recordId, + uploadResult.id, + { + [CardMappings.Active__c]: isCardActive, + } + ); + + if (!updateResult.success) { + uploadResult.hasErrors = true; + uploadResult.errors = uploadResult.errors || []; + + uploadResult.errors.push(this.messages.getMessage('errorWhileActivatingCard') + updateResult.errors); + } + } + } catch (err) { + this.setRecordErrors(card, this.messages.getMessage('errorWhileUploadingCard') + err); + originalRecords.set(recordId, card); + + cardsUploadInfo.set(recordId, { + referenceId: recordId, + hasErrors: true, + success: false, + errors: err, + warnings: [], + }); + } + } + + private getChildCards(card: AnyJson): string[] { + let childs = []; + const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']); + if (!definition) return childs; + + for (let state of definition.states || []) { + if (state.childCards && Array.isArray(state.childCards)) { + childs = childs.concat(state.childCards); + + // Modify the name of the child cards + state.childCards = state.childCards.map((c) => this.cleanName(c)); + } + } + + return childs; + } + + private updateChildCards(card: AnyJson): void { + const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']); + if (!definition) return; + + for (let state of definition.states || []) { + if (state.childCards && Array.isArray(state.childCards)) { + state.childCards = state.childCards.map((c) => this.cleanName(c)); + } + } + + card[this.namespacePrefix + 'Definition__c'] = JSON.stringify(definition); + } + + // Maps an indivitdual VlocityCard__c record to an OmniUiCard record. + private mapVlocityCardRecord( + cardRecord: AnyJson, + cardsUploadInfo: Map, + invalidIpNames: Map + ): AnyJson { + // Transformed object + const mappedObject = {}; + + // Get the fields of the record + const recordFields = Object.keys(cardRecord); + + // Map individual fields + recordFields.forEach((recordField) => { + const cleanFieldName = this.getCleanFieldName(recordField); + + if (CardMappings.hasOwnProperty(cleanFieldName) && cleanFieldName !== 'IsChildCard__c') { + mappedObject[CardMappings[cleanFieldName]] = cardRecord[recordField]; + + // Transform ParentId__c to ClonedFromOmniUiCardKey field from uploaded response map + if (cleanFieldName === 'ParentID__c' && cardsUploadInfo.has(cardRecord[`${this.namespacePrefix}ParentID__c`])) { + mappedObject[CardMappings[cleanFieldName]] = cardsUploadInfo.get( + cardRecord[`${this.namespacePrefix}ParentID__c`] + ).id; + } + + // CardType__c and OmniUiCardType have different picklist values + if (cleanFieldName === 'CardType__c') { + let ischildCard = cardRecord[`${this.namespacePrefix}IsChildCard__c`]; + mappedObject['OmniUiCardType'] = ischildCard ? 'Child' : 'Parent'; + } + + // Child Cards don't have version, so assigning 1 + if (cleanFieldName === 'Version__c') { + let versionNumber = cardRecord[`${this.namespacePrefix}Version__c`]; + mappedObject['VersionNumber'] = versionNumber ? versionNumber : 1; + } + } + }); + + // Clean the name + mappedObject['Name'] = this.cleanName(mappedObject['Name']); + mappedObject[CardMappings.Author__c] = this.cleanName(mappedObject[CardMappings.Author__c]); + mappedObject[CardMappings.Active__c] = false; + + // Update the datasource + const datasource = JSON.parse(mappedObject[CardMappings.Datasource__c] || '{}'); + if (datasource.dataSource) { + const type = datasource.dataSource.type; + if (type === 'DataRaptor') { + datasource.dataSource.value.bundle = this.cleanName(datasource.dataSource.value.bundle); + } else if (type === 'IntegrationProcedures') { + const ipMethod: string = datasource.dataSource.value.ipMethod || ''; + + const parts = ipMethod.split('_'); + const newKey = parts.map((p) => this.cleanName(p, true)).join('_'); + + datasource.dataSource.value.ipMethod = newKey; + + if (parts.length > 2) { + invalidIpNames.set('DataSource', ipMethod); + } + } + mappedObject[CardMappings.Datasource__c] = JSON.stringify(datasource); + } + + // Update the propertyset datasource + const propertySet = JSON.parse(mappedObject[CardMappings.Definition__c] || '{}'); + if (propertySet) { + if (propertySet.dataSource) { + const type = propertySet.dataSource.type; + if (type === 'DataRaptor') { + propertySet.dataSource.value.bundle = this.cleanName(propertySet.dataSource.value.bundle); + } else if (type === 'IntegrationProcedures') { + const ipMethod: string = propertySet.dataSource.value.ipMethod || ''; + + const parts = ipMethod.split('_'); + const newKey = parts.map((p) => this.cleanName(p, true)).join('_'); + propertySet.dataSource.value.ipMethod = newKey; + + if (parts.length > 2) { + invalidIpNames.set('DataSource', ipMethod); + } + } + } + + // update the states for child cards + for (let i = 0; i < (propertySet.states || []).length; i++) { + const state = propertySet.states[i]; + + // Clean childCards property + if (state.childCards && Array.isArray(state.childCards)) { + state.childCards = state.childCards.map((c) => this.cleanName(c)); + } + + // Fix the "components" for child cards + for (let componentKey in state.components) { + if (state.components.hasOwnProperty(componentKey)) { + const component = state.components[componentKey]; + + if (component.children && Array.isArray(component.children)) { + this.fixChildren(component.children); + } + } + } + + if (state.omniscripts && Array.isArray(state.omniscripts)) { + for (let osIdx = 0; osIdx < state.omniscripts.length; osIdx++) { + state.omniscripts[osIdx].type = this.cleanName(state.omniscripts[osIdx].type); + state.omniscripts[osIdx].subtype = this.cleanName(state.omniscripts[osIdx].subtype); + } + } + } + + mappedObject[CardMappings.Definition__c] = JSON.stringify(propertySet); + } + + mappedObject['attributes'] = { + type: CardMigrationTool.OMNIUICARD_NAME, + referenceId: cardRecord['Id'], + }; + + return mappedObject; + } + + private fixChildren(children: any[]) { + for (let j = 0; j < children.length; j++) { + const child = children[j]; + + if (child.element === 'childCardPreview') { + child.property.cardName = this.cleanName(child.property.cardName); + } else if (child.element === 'action') { + if (child.property && child.property.stateAction && child.property.stateAction.omniType) { + const parts = (child.property.stateAction.omniType.Name || '').split('/'); + child.property.stateAction.omniType.Name = parts.map((p) => this.cleanName(p)).join('/'); + } + } + + if (child.children && Array.isArray(child.children)) { + this.fixChildren(child.children); + } + } + } + + private getCardFields(): string[] { + return Object.keys(CardMappings); + } +} diff --git a/src/migration/omniscript.ts b/src/migration/omniscript.ts index 8e7e3036..490285e0 100644 --- a/src/migration/omniscript.ts +++ b/src/migration/omniscript.ts @@ -13,571 +13,725 @@ import { Connection, Logger, Messages } from '@salesforce/core'; import { UX } from '@salesforce/command'; export class OmniScriptMigrationTool extends BaseMigrationTool implements MigrationTool { - - private readonly exportType: OmniScriptExportType; - - // Source Custom Object Names - static readonly OMNISCRIPT_NAME = 'OmniScript__c'; - static readonly ELEMENT_NAME = 'Element__c'; - static readonly OMNISCRIPTDEFINITION_NAME = 'OmniScriptDefinition__c'; - - // Target Standard Objects Name - static readonly OMNIPROCESS_NAME = 'OmniProcess'; - static readonly OMNIPROCESSELEMENT_NAME = 'OmniProcessElement'; - static readonly OMNIPROCESSCOMPILATION_NAME = 'OmniProcessCompilation'; - - constructor(exportType: OmniScriptExportType, namespace: string, connection: Connection, logger: Logger, messages: Messages, ux: UX) { - super(namespace, connection, logger, messages, ux); - this.exportType = exportType; - } - - getName(): string { - return "OmniScript / Integration Procedures"; - } - - getRecordName(record: string) { - return record[this.namespacePrefix + 'Type__c'] - + '_' - + record[this.namespacePrefix + 'SubType__c'] - + (record[this.namespacePrefix + 'Language__c'] ? '_' + record[this.namespacePrefix + 'Language__c'] : '') - + '_' - + record[this.namespacePrefix + 'Version__c']; - } - - getMappings(): ObjectMapping[] { - return [{ - source: OmniScriptMigrationTool.OMNISCRIPT_NAME, - target: OmniScriptMigrationTool.OMNIPROCESS_NAME - }, { - source: OmniScriptMigrationTool.ELEMENT_NAME, - target: OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME - }, { - source: OmniScriptMigrationTool.OMNISCRIPTDEFINITION_NAME, - target: OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME - }]; - } - - async truncate(): Promise { - const objectName = OmniScriptMigrationTool.OMNIPROCESS_NAME; - - const allIds = await this.deactivateRecord(objectName); - await this.truncateElements(objectName, allIds.os.parents); - await this.truncateElements(objectName, allIds.os.childs); - await this.truncateElements(objectName, allIds.ip.parents); - await this.truncateElements(objectName, allIds.ip.childs); - } - - async truncateElements(objectName: string, ids: string[]): Promise { - if (!ids || ids.length === 0) { return; } - - let success: boolean = await NetUtils.delete(this.connection, ids); - if (!success) { - throw new Error(this.messages.getMessage('couldNotTruncateOmnniProcess').formatUnicorn(objectName)); - } - } - - async deactivateRecord(objectName: string): Promise<{ os: { parents: string[], childs: string[] }, ip: { parents: string[], childs: string[] } }> { - DebugTimer.getInstance().lap('Truncating ' + objectName + ' (' + this.exportType + ')'); - - const filters = new Map(); - const sorting = [{ field: 'IsIntegrationProcedure', direction: SortDirection.ASC }, { field: 'IsOmniScriptEmbeddable', direction: SortDirection.ASC }]; - - // Filter if only IP / OS - if (this.exportType === OmniScriptExportType.IP) { - filters.set('IsIntegrationProcedure', true); - } else if (this.exportType === OmniScriptExportType.OS) { - filters.set('IsIntegrationProcedure', false); - } - - // const ids: string[] = await QueryTools.queryIds(this.connection, objectName, filters); - const rows = await QueryTools.query(this.connection, objectName, ['Id', 'IsIntegrationProcedure', 'IsOmniScriptEmbeddable'], filters, sorting); - if (rows.length === 0) { - return { os: { parents: [], childs: [] }, ip: { parents: [], childs: [] } }; - } - - // We need to update one item at time. Otherwise, we'll have an UNKNOWN_ERROR - for (let row of rows) { - const id = row['Id']; - - await NetUtils.request(this.connection, `sobjects/${OmniScriptMigrationTool.OMNIPROCESS_NAME}/${id}`, { - IsActive: false - }, RequestMethod.PATCH); - } - - // Sleep 5 seconds, let's wait for all row locks to be released. While this takes less than a second, there has been - // times where it take a bit more. - await this.sleep(); - - return { - os: { - parents: rows.filter(row => row.IsIntegrationProcedure === false && row.IsOmniScriptEmbeddable === false).map(row => row.Id), - childs: rows.filter(row => row.IsIntegrationProcedure === false && row.IsOmniScriptEmbeddable === true).map(row => row.Id), - }, - ip: { - parents: rows.filter(row => row.IsIntegrationProcedure === true && row.IsOmniScriptEmbeddable === false).map(row => row.Id), - childs: rows.filter(row => row.IsIntegrationProcedure === true && row.IsOmniScriptEmbeddable === true).map(row => row.Id) - } - }; - } - - async migrate(): Promise { - - // Get All Records from OmniScript__c (IP & OS Parent Records) - const omniscripts = await this.getAllOmniScripts(); - const duplicatedNames = new Set(); - - // Variables to be returned After Migration - let done = 0; - let originalOsRecords = new Map(); - let osUploadInfo = new Map(); - const total = omniscripts.length; - - for (let omniscript of omniscripts) { - const mappedRecords = []; - // const originalRecords = new Map(); - const recordId = omniscript['Id']; - - this.reportProgress(total, done); - - // Record is Active, Elements can't be Added, Modified or Deleted for that OS/IP - omniscript[`${this.namespacePrefix}IsActive__c`] = false; - - // Create a map of the original OmniScript__c records - originalOsRecords.set(recordId, omniscript); - - // Get All elements for each OmniScript__c record(i.e IP/OS) - const elements = await this.getAllElementsForOmniScript(recordId); - - // Perform the transformation for OS/IP Parent Record from OmniScript__c - const mappedOmniScript = this.mapOmniScriptRecord(omniscript); - - // Clean type, subtype - mappedOmniScript[OmniScriptMappings.Type__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.Type__c]); - mappedOmniScript[OmniScriptMappings.SubType__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.SubType__c]); - - // Check duplicated name - // const mappedOsName = `${mappedOmniScript[OmniScriptMappings.Type__c]}_${mappedOmniScript[OmniScriptMappings.SubType__c]}_${mappedOmniScript[OmniScriptMappings.Language__c]}`; - const mappedOsName = mappedOmniScript[OmniScriptMappings.Type__c] + '_' + mappedOmniScript[OmniScriptMappings.SubType__c] - + (mappedOmniScript[OmniScriptMappings.Language__c] ? '_' + mappedOmniScript[OmniScriptMappings.Language__c] : '') + '_1'; - - if (duplicatedNames.has(mappedOsName)) { - this.setRecordErrors(omniscript, this.messages.getMessage('duplicatedOSName')); - originalOsRecords.set(recordId, omniscript) - continue; - } - - // Save the mapped record - duplicatedNames.add(mappedOsName); - mappedRecords.push(mappedOmniScript); - - // Save the OmniScript__c records to Standard BPO i.e OmniProcess - const osUploadResponse = await NetUtils.createOne(this.connection, OmniScriptMigrationTool.OMNIPROCESS_NAME, recordId, mappedOmniScript); - - if (osUploadResponse.success) { - - // Fix errors - if (!osUploadResponse.success) { - osUploadResponse.errors = Array.isArray(osUploadResponse.errors) ? osUploadResponse.errors : [osUploadResponse.errors]; - } - - osUploadResponse.warnings = osUploadResponse.warnings || []; - - const originalOsName = omniscript[this.namespacePrefix + 'Type__c'] + '_' + omniscript[this.namespacePrefix + 'SubType__c'] + '_' + omniscript[this.namespacePrefix + 'Language__c']; - if (originalOsName !== mappedOsName) { - osUploadResponse.newName = mappedOsName; - osUploadResponse.warnings.unshift('WARNING: OmniScript name has been modified to fit naming rules: ' + mappedOsName); - } - - try { - // Upload All elements for each OmniScript__c record(i.e IP/OS) - await this.uploadAllElements(osUploadResponse, elements); - - // Get OmniScript Compiled Definitions for OmniScript Record - const omniscriptsCompiledDefinitions = await this.getOmniScriptCompiledDefinition(recordId); - - // Upload OmniScript Compiled Definition to OmniProcessCompilation - await this.uploadAllOmniScriptDefinitions(osUploadResponse, omniscriptsCompiledDefinitions); - - // Update the inserted OS record as it was Active and made InActive to insert. - mappedRecords[0].IsActive = true; - mappedRecords[0].Id = osUploadResponse.id; - - if (mappedRecords[0].IsIntegrationProcedure) { - mappedRecords[0].Language = 'Procedure'; - } - - const updateResult = await NetUtils.updateOne(this.connection, OmniScriptMigrationTool.OMNIPROCESS_NAME, recordId, osUploadResponse.id, { - [OmniScriptMappings.IsActive__c]: true - }); - - if (!updateResult.success) { - osUploadResponse.hasErrors = true; - osUploadResponse.errors = osUploadResponse.errors || []; - - osUploadResponse.errors.push(this.messages.getMessage('errorWhileActivatingOs') + updateResult.errors); - } - - - } catch (e) { - osUploadResponse.hasErrors = true; - osUploadResponse.errors = osUploadResponse.errors || []; - - let error = 'UNKNOWN'; - if (typeof e === 'object') { - try { - const obj = JSON.parse(e.message || '{}'); - if (obj.hasErrors && obj.results && Array.isArray(obj.results)) { - error = obj.results.map(r => { - return Array.isArray(r.errors) ? r.errors.map(e => e.message).join('. ') : r.errors; - }).join('. '); - } - } catch { - error = e.toString(); - } - } - - osUploadResponse.errors.push(this.messages.getMessage('errorWhileCreatingElements') + error); - } - finally { - // Create the return records and response which have been processed - osUploadInfo.set(recordId, osUploadResponse); - } - } - - originalOsRecords.set(recordId, omniscript); - - done++; - }; - - const objectMigrationResults: MigrationResult[] = []; - - if (this.exportType === OmniScriptExportType.All || this.exportType === OmniScriptExportType.IP) { - objectMigrationResults.push(this.getMigratedRecordsByType('Integration Procedures', osUploadInfo, originalOsRecords)); - } - if (this.exportType === OmniScriptExportType.All || this.exportType === OmniScriptExportType.OS) { - objectMigrationResults.push(this.getMigratedRecordsByType('OmniScripts', osUploadInfo, originalOsRecords)); - } - - return objectMigrationResults; - } - - // Using this small method, As IP & OS lives in same object -> So returning the IP and OS in the end, after the migration is done - // and the results are generated. Other way can be creating a separate IP class and migrating IP & OS separately - // using common functions - private getMigratedRecordsByType(type: string, results: Map, records: Map): MigrationResult { - let recordMap: Map = new Map(); - let resultMap: Map = new Map(); - for (let record of Array.from(records.values())) { - if (type === 'Integration Procedures' && record[`${this.namespacePrefix}IsProcedure__c`] || - type === 'OmniScripts' && !record[`${this.namespacePrefix}IsProcedure__c`] - ) { - recordMap.set(record['Id'], records.get(record['Id'])); - if (results.get(record['Id'])) { - resultMap.set(record['Id'], results.get(record['Id'])); - } - } - } - return { - name: type, - records: recordMap, - results: resultMap - } - } - - // Get All OmniScript__c records i.e All IP & OS - private async getAllOmniScripts(): Promise { - DebugTimer.getInstance().lap('Query OmniScripts'); - - const filters = new Map(); - filters.set(this.namespacePrefix + 'IsActive__c', true); - - if (this.exportType === OmniScriptExportType.IP) { - filters.set(this.namespacePrefix + 'IsProcedure__c', true); - } else if (this.exportType === OmniScriptExportType.OS) { - filters.set(this.namespacePrefix + 'IsProcedure__c', false); - } - - return await QueryTools.queryWithFilter(this.connection, this.namespace, OmniScriptMigrationTool.OMNISCRIPT_NAME, this.getOmniScriptFields(), filters); - } - - // Get All Elements w.r.t OmniScript__c i.e Elements tagged to passed in IP/OS - private async getAllElementsForOmniScript(recordId: string): Promise { - // Query all Elements for an OmniScript - const filters = new Map(); - filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId); - - // const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`; - return await QueryTools.queryWithFilter(this.connection, this.namespace, OmniScriptMigrationTool.ELEMENT_NAME, this.getElementFields(), filters); - } - - // Get All Compiled Definitions w.r.t OmniScript__c i.e Definitions tagged to passed in IP/OS - private async getOmniScriptCompiledDefinition(recordId: string): Promise { - // Query all Definitions for an OmniScript - const filters = new Map(); - filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId); - - // const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`; - return await QueryTools.queryWithFilter(this.connection, this.namespace, OmniScriptMigrationTool.OMNISCRIPTDEFINITION_NAME, this.getOmniScriptDefinitionFields(), filters); - } - - // Upload All the Elements tagged to a OmniScript__c record, after the parent record has been inserted - private async uploadAllElements(omniScriptUploadResults: UploadRecordResult, elements: AnyJson[]): Promise> { - let levelCount = 0; // To define and insert different levels(Parent-Child relationship) at a time - let exit = false; // Counter variable to exit after all parent-child elements inserted - var elementsUploadInfo = new Map(); // Info for Uploaded Elements to be returned - - do { - let tempElements = []; // Stores Elements at a same level starting with levelCount = 0 level (parent elements) - for (let element of elements) { - if (element[`${this.namespacePrefix}Level__c`] === levelCount) { - let elementId = element['Id']; - let elementParentId = element[`${this.namespacePrefix}ParentElementId__c`]; - if (!elementsUploadInfo.has(elementId) && (!elementParentId || (elementParentId && elementsUploadInfo.has(elementParentId)))) { - tempElements.push(element); - } - } - } - - // If no elements exist after a certain level, Then everything is alraedy processed, otherwise upload - if (tempElements.length === 0) { - exit = true; - } else { - // Get Transformed Element__c to OmniProcessElement with updated OmniScriptId & ParentElementId - let elementsTransformedData = await this.prepareElementsData(omniScriptUploadResults, tempElements, elementsUploadInfo); - // Upload the transformed Element__c - let elementsUploadResponse = await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, elementsTransformedData); - // Keep appending upload Info for Elements at each level - elementsUploadInfo = new Map([...Array.from(elementsUploadInfo.entries()), ...Array.from(elementsUploadResponse.entries())]); - } - - levelCount++; - - } while (exit === false) - - return elementsUploadInfo; - } - - // Upload All the Definitions tagged to a OmniScript__c record, after the parent record has been inserted - private async uploadAllOmniScriptDefinitions(omniScriptUploadResults: UploadRecordResult, osDefinitions: AnyJson[]): Promise> { - let osDefinitionsData = await this.prepareOsDefinitionsData(omniScriptUploadResults, osDefinitions); - return await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, osDefinitionsData); - } - - // Prepare Elements Data and Do the neccessary updates, transformation, validations etc. - private async prepareElementsData(osUploadResult: UploadRecordResult, elements: AnyJson[], parentElementUploadResponse: Map): Promise { - - const mappedRecords = [], - originalRecords = new Map(), - invalidIpNames = new Map(); - - elements.forEach(element => { - - // Perform the transformation. We need parent record & must have been migrated before - if (osUploadResult.id) { - mappedRecords.push(this.mapElementData(element, osUploadResult.id, parentElementUploadResponse, invalidIpNames)); - } - - // Create a map of the original records - originalRecords.set(element['Id'], element); - }); - - if (osUploadResult.id && invalidIpNames.size > 0) { - const val = Array.from(invalidIpNames.entries()).map(e => e[0]).join(', '); - osUploadResult.errors.push('Integration Procedure Actions will need manual updates, please verify: ' + val); - } - - return { originalRecords, mappedRecords }; - } - - // Prepare OmniScript Definitions to be uploaded - private async prepareOsDefinitionsData(osUploadResult: UploadRecordResult, osDefinitions: AnyJson[]): Promise { - const mappedRecords = [], - originalRecords = new Map(); - - osDefinitions.forEach(osDefinition => { - - // Perform the transformation. We need parent record & must have been migrated before - if (osUploadResult.id) { - mappedRecords.push(this.mapOsDefinitionsData(osDefinition, osUploadResult.id)); - } - - // Create a map of the original records - originalRecords.set(osDefinition['Id'], osDefinition); - }); - - return { originalRecords, mappedRecords }; - } - - /** - * Maps an omniscript__c record to OmniProcess Record. - * @param omniScriptRecord - * @returns - */ - private mapOmniScriptRecord(omniScriptRecord: AnyJson): AnyJson { - - // Transformed object - const mappedObject = {}; - - // Get the fields of the record - const recordFields = Object.keys(omniScriptRecord); - - // Map individual fields - recordFields.forEach(recordField => { - const cleanFieldName = this.getCleanFieldName(recordField); - - if (OmniScriptMappings.hasOwnProperty(cleanFieldName)) { - mappedObject[OmniScriptMappings[cleanFieldName]] = omniScriptRecord[recordField]; - } - }); - - mappedObject['Name'] = this.cleanName(mappedObject['Name']); - - // BATCH framework requires that each record has an "attributes" property - mappedObject['attributes'] = { - type: OmniScriptMigrationTool.OMNIPROCESS_NAME, - referenceId: omniScriptRecord['Id'] - }; - - return mappedObject; - } - - // Maps an individual Element into an OmniProcessElement record - private mapElementData(elementRecord: AnyJson, omniProcessId: string, parentElementUploadResponse: Map, invalidIpReferences: Map) { - - // Transformed object - const mappedObject = {}; - - // Get the fields of the record - const recordFields = Object.keys(elementRecord); - - // Map individual fields - recordFields.forEach(recordField => { - const cleanFieldName = this.getCleanFieldName(recordField); - - if (ElementMappings.hasOwnProperty(cleanFieldName)) { - mappedObject[ElementMappings[cleanFieldName]] = elementRecord[recordField]; - - if (cleanFieldName === "ParentElementId__c" && parentElementUploadResponse.has(elementRecord[`${this.namespacePrefix}ParentElementId__c`])) { - mappedObject[ElementMappings[cleanFieldName]] = parentElementUploadResponse.get(elementRecord[`${this.namespacePrefix}ParentElementId__c`]).id; - } - } - }); - - // Set the parent/child relationship - mappedObject['OmniProcessId'] = omniProcessId; - - // We need to fix the child references - const elementType = mappedObject[ElementMappings.Type__c]; - const propertySet = JSON.parse(mappedObject[ElementMappings.PropertySet__c] || '{}'); - switch (elementType) { - case 'OmniScript': - propertySet['Type'] = this.cleanName(propertySet['Type']); - propertySet['Sub Type'] = this.cleanName(propertySet['Sub Type']); - break; - case 'Integration Procedure Action': - const remoteOptions = propertySet['remoteOptions'] || {}; - remoteOptions['preTransformBundle'] = this.cleanName(remoteOptions['preTransformBundle']); - remoteOptions['postTransformBundle'] = this.cleanName(remoteOptions['postTransformBundle']); - propertySet['remoteOptions'] = remoteOptions; - - propertySet['preTransformBundle'] = this.cleanName(propertySet['preTransformBundle']); - propertySet['postTransformBundle'] = this.cleanName(propertySet['postTransformBundle']); - - // We can't update the IP references, we need to let the user know - const key: String = propertySet['integrationProcedureKey'] || ''; - if (key) { - const parts = key.split('_'); - const newKey = parts.map(p => this.cleanName(p, true)).join('_'); - if (parts.length > 2) { - invalidIpReferences.set(mappedObject[ElementMappings.Name], key); - } - propertySet['integrationProcedureKey'] = newKey; - } - break; - case 'DataRaptor Turbo Action': - case 'DataRaptor Transform Action': - case 'DataRaptor Post Action': - case 'DataRaptor Extract Action': - propertySet['bundle'] = this.cleanName(propertySet['bundle']); - break; - } - - mappedObject[ElementMappings.PropertySet__c] = JSON.stringify(propertySet); - mappedObject['Name'] = this.cleanName(mappedObject['Name']); - - // BATCH framework requires that each record has an "attributes" property - mappedObject['attributes'] = { - type: OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, - referenceId: elementRecord['Id'] - }; - - return mappedObject; - } - - // Maps an individual Definition into an OmniProcessCompilation record - private mapOsDefinitionsData(osDefinition: AnyJson, omniProcessId: string) { - // Transformed object - const mappedObject = {}; - - // Get the fields of the record - const recordFields = Object.keys(osDefinition); - - // Map individual fields - recordFields.forEach(recordField => { - const cleanFieldName = this.getCleanFieldName(recordField); - - if (OmniScriptDefinitionMappings.hasOwnProperty(cleanFieldName)) { - mappedObject[OmniScriptDefinitionMappings[cleanFieldName]] = osDefinition[recordField]; - } - }); - - // Set the parent/child relationship - mappedObject[OmniScriptDefinitionMappings.Name] = omniProcessId; - mappedObject[OmniScriptDefinitionMappings.OmniScriptId__c] = omniProcessId; - - let content = mappedObject[OmniScriptDefinitionMappings.Content__c]; - if (content) { - try { - content = JSON.parse(content); - if (content && content['sOmniScriptId']) { - content['sOmniScriptId'] = omniProcessId; - mappedObject[OmniScriptDefinitionMappings.Content__c] = JSON.stringify(content); - } - } catch (ex) { - // Log - } - } - - // BATCH framework requires that each record has an "attributes" property - mappedObject['attributes'] = { - type: OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, - referenceId: osDefinition['Id'] - }; - - return mappedObject; - } - - private getOmniScriptFields(): string[] { - return Object.keys(OmniScriptMappings); - } - - private getElementFields(): string[] { - return Object.keys(ElementMappings); - } - - private getOmniScriptDefinitionFields(): string[] { - return Object.keys(OmniScriptDefinitionMappings); - } - - private sleep() { - return new Promise(resolve => { - setTimeout(resolve, 5000); - }) - }; + private readonly exportType: OmniScriptExportType; + private readonly allVersions: boolean; + + // Source Custom Object Names + static readonly OMNISCRIPT_NAME = 'OmniScript__c'; + static readonly ELEMENT_NAME = 'Element__c'; + static readonly OMNISCRIPTDEFINITION_NAME = 'OmniScriptDefinition__c'; + + // Target Standard Objects Name + static readonly OMNIPROCESS_NAME = 'OmniProcess'; + static readonly OMNIPROCESSELEMENT_NAME = 'OmniProcessElement'; + static readonly OMNIPROCESSCOMPILATION_NAME = 'OmniProcessCompilation'; + + constructor( + exportType: OmniScriptExportType, + namespace: string, + connection: Connection, + logger: Logger, + messages: Messages, + ux: UX, + allVersions: boolean + ) { + super(namespace, connection, logger, messages, ux); + this.exportType = exportType; + this.allVersions = allVersions; + } + + getName(): string { + return 'OmniScript / Integration Procedures'; + } + + getRecordName(record: string) { + return ( + record[this.namespacePrefix + 'Type__c'] + + '_' + + record[this.namespacePrefix + 'SubType__c'] + + (record[this.namespacePrefix + 'Language__c'] ? '_' + record[this.namespacePrefix + 'Language__c'] : '') + + '_' + + record[this.namespacePrefix + 'Version__c'] + ); + } + + getMappings(): ObjectMapping[] { + return [ + { + source: OmniScriptMigrationTool.OMNISCRIPT_NAME, + target: OmniScriptMigrationTool.OMNIPROCESS_NAME, + }, + { + source: OmniScriptMigrationTool.ELEMENT_NAME, + target: OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, + }, + { + source: OmniScriptMigrationTool.OMNISCRIPTDEFINITION_NAME, + target: OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, + }, + ]; + } + + async truncate(): Promise { + const objectName = OmniScriptMigrationTool.OMNIPROCESS_NAME; + const allIds = await this.deactivateRecord(objectName); + await this.truncateElements(objectName, allIds.os.parents); + await this.truncateElements(objectName, allIds.os.childs); + await this.truncateElements(objectName, allIds.ip.parents); + await this.truncateElements(objectName, allIds.ip.childs); + } + + async truncateElements(objectName: string, ids: string[]): Promise { + if (!ids || ids.length === 0) { + return; + } + + let success: boolean = await NetUtils.delete(this.connection, ids); + if (!success) { + throw new Error(this.messages.getMessage('couldNotTruncateOmnniProcess').formatUnicorn(objectName)); + } + } + + async deactivateRecord( + objectName: string + ): Promise<{ os: { parents: string[]; childs: string[] }; ip: { parents: string[]; childs: string[] } }> { + DebugTimer.getInstance().lap('Truncating ' + objectName + ' (' + this.exportType + ')'); + + const filters = new Map(); + const sorting = [ + { field: 'IsIntegrationProcedure', direction: SortDirection.ASC }, + { field: 'IsOmniScriptEmbeddable', direction: SortDirection.ASC }, + ]; + + // Filter if only IP / OS + if (this.exportType === OmniScriptExportType.IP) { + filters.set('IsIntegrationProcedure', true); + } else if (this.exportType === OmniScriptExportType.OS) { + filters.set('IsIntegrationProcedure', false); + } + + // const ids: string[] = await QueryTools.queryIds(this.connection, objectName, filters); + const rows = await QueryTools.query( + this.connection, + objectName, + ['Id', 'IsIntegrationProcedure', 'IsOmniScriptEmbeddable'], + filters, + sorting + ); + if (rows.length === 0) { + return { os: { parents: [], childs: [] }, ip: { parents: [], childs: [] } }; + } + + // We need to update one item at time. Otherwise, we'll have an UNKNOWN_ERROR + for (let row of rows) { + const id = row['Id']; + + await NetUtils.request( + this.connection, + `sobjects/${OmniScriptMigrationTool.OMNIPROCESS_NAME}/${id}`, + { + IsActive: false, + }, + RequestMethod.PATCH + ); + } + + // Sleep 5 seconds, let's wait for all row locks to be released. While this takes less than a second, there has been + // times where it take a bit more. + await this.sleep(); + + return { + os: { + parents: rows + .filter((row) => row.IsIntegrationProcedure === false && row.IsOmniScriptEmbeddable === false) + .map((row) => row.Id), + childs: rows + .filter((row) => row.IsIntegrationProcedure === false && row.IsOmniScriptEmbeddable === true) + .map((row) => row.Id), + }, + ip: { + parents: rows + .filter((row) => row.IsIntegrationProcedure === true && row.IsOmniScriptEmbeddable === false) + .map((row) => row.Id), + childs: rows + .filter((row) => row.IsIntegrationProcedure === true && row.IsOmniScriptEmbeddable === true) + .map((row) => row.Id), + }, + }; + } + + async migrate(): Promise { + // Get All Records from OmniScript__c (IP & OS Parent Records) + const omniscripts = await this.getAllOmniScripts(); + const duplicatedNames = new Set(); + + // Variables to be returned After Migration + let done = 0; + let originalOsRecords = new Map(); + let osUploadInfo = new Map(); + const total = omniscripts.length; + + for (let omniscript of omniscripts) { + const mappedRecords = []; + // const originalRecords = new Map(); + const recordId = omniscript['Id']; + const isOsActive = omniscript[`${this.namespacePrefix}IsActive__c`]; + + this.reportProgress(total, done); + + // Create a map of the original OmniScript__c records + originalOsRecords.set(recordId, omniscript); + + // Record is Active, Elements can't be Added, Modified or Deleted for that OS/IP + omniscript[`${this.namespacePrefix}IsActive__c`] = false; + + // Get All elements for each OmniScript__c record(i.e IP/OS) + const elements = await this.getAllElementsForOmniScript(recordId); + + // Perform the transformation for OS/IP Parent Record from OmniScript__c + const mappedOmniScript = this.mapOmniScriptRecord(omniscript); + + // Clean type, subtype + mappedOmniScript[OmniScriptMappings.Type__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.Type__c]); + mappedOmniScript[OmniScriptMappings.SubType__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.SubType__c]); + + // Check duplicated name + let mappedOsName; + if (this.allVersions) { + mappedOmniScript[OmniScriptMappings.Version__c] = omniscript[`${this.namespacePrefix}Version__c`]; + mappedOsName = + mappedOmniScript[OmniScriptMappings.Type__c] + + '_' + + mappedOmniScript[OmniScriptMappings.SubType__c] + + (mappedOmniScript[OmniScriptMappings.Language__c] + ? '_' + mappedOmniScript[OmniScriptMappings.Language__c] + : '') + + '_' + + mappedOmniScript[OmniScriptMappings.Version__c]; + } else { + mappedOsName = + mappedOmniScript[OmniScriptMappings.Type__c] + + '_' + + mappedOmniScript[OmniScriptMappings.SubType__c] + + (mappedOmniScript[OmniScriptMappings.Language__c] + ? '_' + mappedOmniScript[OmniScriptMappings.Language__c] + : '') + + '_1'; + } + + if (duplicatedNames.has(mappedOsName)) { + this.setRecordErrors(omniscript, this.messages.getMessage('duplicatedOSName')); + originalOsRecords.set(recordId, omniscript); + continue; + } + + // Save the mapped record + duplicatedNames.add(mappedOsName); + mappedRecords.push(mappedOmniScript); + + // Save the OmniScript__c records to Standard BPO i.e OmniProcess + const osUploadResponse = await NetUtils.createOne( + this.connection, + OmniScriptMigrationTool.OMNIPROCESS_NAME, + recordId, + mappedOmniScript + ); + + if (osUploadResponse.success) { + // Fix errors + if (!osUploadResponse.success) { + osUploadResponse.errors = Array.isArray(osUploadResponse.errors) + ? osUploadResponse.errors + : [osUploadResponse.errors]; + } + + osUploadResponse.warnings = osUploadResponse.warnings || []; + + const originalOsName = + omniscript[this.namespacePrefix + 'Type__c'] + + '_' + + omniscript[this.namespacePrefix + 'SubType__c'] + + '_' + + omniscript[this.namespacePrefix + 'Language__c']; + if (originalOsName !== mappedOsName) { + osUploadResponse.newName = mappedOsName; + osUploadResponse.warnings.unshift( + 'WARNING: OmniScript name has been modified to fit naming rules: ' + mappedOsName + ); + } + + try { + // Upload All elements for each OmniScript__c record(i.e IP/OS) + await this.uploadAllElements(osUploadResponse, elements); + + // Get OmniScript Compiled Definitions for OmniScript Record + const omniscriptsCompiledDefinitions = await this.getOmniScriptCompiledDefinition(recordId); + + // Upload OmniScript Compiled Definition to OmniProcessCompilation + await this.uploadAllOmniScriptDefinitions(osUploadResponse, omniscriptsCompiledDefinitions); + + if (isOsActive) { + // Update the inserted OS record as it was Active and made InActive to insert. + mappedRecords[0].IsActive = true; + mappedRecords[0].Id = osUploadResponse.id; + + if (mappedRecords[0].IsIntegrationProcedure) { + mappedRecords[0].Language = 'Procedure'; + } + + const updateResult = await NetUtils.updateOne( + this.connection, + OmniScriptMigrationTool.OMNIPROCESS_NAME, + recordId, + osUploadResponse.id, + { + [OmniScriptMappings.IsActive__c]: true, + } + ); + + if (!updateResult.success) { + osUploadResponse.hasErrors = true; + osUploadResponse.errors = osUploadResponse.errors || []; + + osUploadResponse.errors.push(this.messages.getMessage('errorWhileActivatingOs') + updateResult.errors); + } + } + } catch (e) { + osUploadResponse.hasErrors = true; + osUploadResponse.errors = osUploadResponse.errors || []; + + let error = 'UNKNOWN'; + if (typeof e === 'object') { + try { + const obj = JSON.parse(e.message || '{}'); + if (obj.hasErrors && obj.results && Array.isArray(obj.results)) { + error = obj.results + .map((r) => { + return Array.isArray(r.errors) ? r.errors.map((e) => e.message).join('. ') : r.errors; + }) + .join('. '); + } + } catch { + error = e.toString(); + } + } + + osUploadResponse.errors.push(this.messages.getMessage('errorWhileCreatingElements') + error); + } finally { + // Create the return records and response which have been processed + osUploadInfo.set(recordId, osUploadResponse); + } + } + + originalOsRecords.set(recordId, omniscript); + + done++; + } + + const objectMigrationResults: MigrationResult[] = []; + + if (this.exportType === OmniScriptExportType.All || this.exportType === OmniScriptExportType.IP) { + objectMigrationResults.push( + this.getMigratedRecordsByType('Integration Procedures', osUploadInfo, originalOsRecords) + ); + } + if (this.exportType === OmniScriptExportType.All || this.exportType === OmniScriptExportType.OS) { + objectMigrationResults.push(this.getMigratedRecordsByType('OmniScripts', osUploadInfo, originalOsRecords)); + } + + return objectMigrationResults; + } + + // Using this small method, As IP & OS lives in same object -> So returning the IP and OS in the end, after the migration is done + // and the results are generated. Other way can be creating a separate IP class and migrating IP & OS separately + // using common functions + private getMigratedRecordsByType( + type: string, + results: Map, + records: Map + ): MigrationResult { + let recordMap: Map = new Map(); + let resultMap: Map = new Map(); + for (let record of Array.from(records.values())) { + if ( + (type === 'Integration Procedures' && record[`${this.namespacePrefix}IsProcedure__c`]) || + (type === 'OmniScripts' && !record[`${this.namespacePrefix}IsProcedure__c`]) + ) { + recordMap.set(record['Id'], records.get(record['Id'])); + if (results.get(record['Id'])) { + resultMap.set(record['Id'], results.get(record['Id'])); + } + } + } + return { + name: type, + records: recordMap, + results: resultMap, + }; + } + + // Get All OmniScript__c records i.e All IP & OS + private async getAllOmniScripts(): Promise { + DebugTimer.getInstance().lap('Query OmniScripts'); + this.logger.info('allVersions : ' + this.allVersions); + const filters = new Map(); + + if (this.exportType === OmniScriptExportType.IP) { + filters.set(this.namespacePrefix + 'IsProcedure__c', true); + } else if (this.exportType === OmniScriptExportType.OS) { + filters.set(this.namespacePrefix + 'IsProcedure__c', false); + } + + if (this.allVersions) { + const sortFields = [ + { field: this.namespacePrefix + 'Type__c', direction: SortDirection.ASC }, + { field: this.namespacePrefix + 'SubType__c', direction: SortDirection.ASC }, + { field: this.namespacePrefix + 'Version__c', direction: SortDirection.ASC }, + ]; + return await QueryTools.queryWithFilterAndSort( + this.connection, + this.namespace, + OmniScriptMigrationTool.OMNISCRIPT_NAME, + this.getOmniScriptFields(), + filters, + sortFields + ); + } else { + filters.set(this.namespacePrefix + 'IsActive__c', true); + return await QueryTools.queryWithFilter( + this.connection, + this.namespace, + OmniScriptMigrationTool.OMNISCRIPT_NAME, + this.getOmniScriptFields(), + filters + ); + } + } + + // Get All Elements w.r.t OmniScript__c i.e Elements tagged to passed in IP/OS + private async getAllElementsForOmniScript(recordId: string): Promise { + // Query all Elements for an OmniScript + const filters = new Map(); + filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId); + + // const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`; + return await QueryTools.queryWithFilter( + this.connection, + this.namespace, + OmniScriptMigrationTool.ELEMENT_NAME, + this.getElementFields(), + filters + ); + } + + // Get All Compiled Definitions w.r.t OmniScript__c i.e Definitions tagged to passed in IP/OS + private async getOmniScriptCompiledDefinition(recordId: string): Promise { + // Query all Definitions for an OmniScript + const filters = new Map(); + filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId); + + // const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`; + return await QueryTools.queryWithFilter( + this.connection, + this.namespace, + OmniScriptMigrationTool.OMNISCRIPTDEFINITION_NAME, + this.getOmniScriptDefinitionFields(), + filters + ); + } + + // Upload All the Elements tagged to a OmniScript__c record, after the parent record has been inserted + private async uploadAllElements( + omniScriptUploadResults: UploadRecordResult, + elements: AnyJson[] + ): Promise> { + let levelCount = 0; // To define and insert different levels(Parent-Child relationship) at a time + let exit = false; // Counter variable to exit after all parent-child elements inserted + var elementsUploadInfo = new Map(); // Info for Uploaded Elements to be returned + + do { + let tempElements = []; // Stores Elements at a same level starting with levelCount = 0 level (parent elements) + for (let element of elements) { + if (element[`${this.namespacePrefix}Level__c`] === levelCount) { + let elementId = element['Id']; + let elementParentId = element[`${this.namespacePrefix}ParentElementId__c`]; + if ( + !elementsUploadInfo.has(elementId) && + (!elementParentId || (elementParentId && elementsUploadInfo.has(elementParentId))) + ) { + tempElements.push(element); + } + } + } + + // If no elements exist after a certain level, Then everything is alraedy processed, otherwise upload + if (tempElements.length === 0) { + exit = true; + } else { + // Get Transformed Element__c to OmniProcessElement with updated OmniScriptId & ParentElementId + let elementsTransformedData = await this.prepareElementsData( + omniScriptUploadResults, + tempElements, + elementsUploadInfo + ); + // Upload the transformed Element__c + let elementsUploadResponse = await this.uploadTransformedData( + OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, + elementsTransformedData + ); + // Keep appending upload Info for Elements at each level + elementsUploadInfo = new Map([ + ...Array.from(elementsUploadInfo.entries()), + ...Array.from(elementsUploadResponse.entries()), + ]); + } + + levelCount++; + } while (exit === false); + + return elementsUploadInfo; + } + + // Upload All the Definitions tagged to a OmniScript__c record, after the parent record has been inserted + private async uploadAllOmniScriptDefinitions( + omniScriptUploadResults: UploadRecordResult, + osDefinitions: AnyJson[] + ): Promise> { + let osDefinitionsData = await this.prepareOsDefinitionsData(omniScriptUploadResults, osDefinitions); + return await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, osDefinitionsData); + } + + // Prepare Elements Data and Do the neccessary updates, transformation, validations etc. + private async prepareElementsData( + osUploadResult: UploadRecordResult, + elements: AnyJson[], + parentElementUploadResponse: Map + ): Promise { + const mappedRecords = [], + originalRecords = new Map(), + invalidIpNames = new Map(); + + elements.forEach((element) => { + // Perform the transformation. We need parent record & must have been migrated before + if (osUploadResult.id) { + mappedRecords.push( + this.mapElementData(element, osUploadResult.id, parentElementUploadResponse, invalidIpNames) + ); + } + + // Create a map of the original records + originalRecords.set(element['Id'], element); + }); + + if (osUploadResult.id && invalidIpNames.size > 0) { + const val = Array.from(invalidIpNames.entries()) + .map((e) => e[0]) + .join(', '); + osUploadResult.errors.push('Integration Procedure Actions will need manual updates, please verify: ' + val); + } + + return { originalRecords, mappedRecords }; + } + + // Prepare OmniScript Definitions to be uploaded + private async prepareOsDefinitionsData( + osUploadResult: UploadRecordResult, + osDefinitions: AnyJson[] + ): Promise { + const mappedRecords = [], + originalRecords = new Map(); + + osDefinitions.forEach((osDefinition) => { + // Perform the transformation. We need parent record & must have been migrated before + if (osUploadResult.id) { + mappedRecords.push(this.mapOsDefinitionsData(osDefinition, osUploadResult.id)); + } + + // Create a map of the original records + originalRecords.set(osDefinition['Id'], osDefinition); + }); + + return { originalRecords, mappedRecords }; + } + + /** + * Maps an omniscript__c record to OmniProcess Record. + * @param omniScriptRecord + * @returns + */ + private mapOmniScriptRecord(omniScriptRecord: AnyJson): AnyJson { + // Transformed object + const mappedObject = {}; + + // Get the fields of the record + const recordFields = Object.keys(omniScriptRecord); + + // Map individual fields + recordFields.forEach((recordField) => { + const cleanFieldName = this.getCleanFieldName(recordField); + + if (OmniScriptMappings.hasOwnProperty(cleanFieldName)) { + mappedObject[OmniScriptMappings[cleanFieldName]] = omniScriptRecord[recordField]; + } + }); + + mappedObject['Name'] = this.cleanName(mappedObject['Name']); + + // BATCH framework requires that each record has an "attributes" property + mappedObject['attributes'] = { + type: OmniScriptMigrationTool.OMNIPROCESS_NAME, + referenceId: omniScriptRecord['Id'], + }; + + return mappedObject; + } + + // Maps an individual Element into an OmniProcessElement record + private mapElementData( + elementRecord: AnyJson, + omniProcessId: string, + parentElementUploadResponse: Map, + invalidIpReferences: Map + ) { + // Transformed object + const mappedObject = {}; + + // Get the fields of the record + const recordFields = Object.keys(elementRecord); + + // Map individual fields + recordFields.forEach((recordField) => { + const cleanFieldName = this.getCleanFieldName(recordField); + + if (ElementMappings.hasOwnProperty(cleanFieldName)) { + mappedObject[ElementMappings[cleanFieldName]] = elementRecord[recordField]; + + if ( + cleanFieldName === 'ParentElementId__c' && + parentElementUploadResponse.has(elementRecord[`${this.namespacePrefix}ParentElementId__c`]) + ) { + mappedObject[ElementMappings[cleanFieldName]] = parentElementUploadResponse.get( + elementRecord[`${this.namespacePrefix}ParentElementId__c`] + ).id; + } + } + }); + + // Set the parent/child relationship + mappedObject['OmniProcessId'] = omniProcessId; + + // We need to fix the child references + const elementType = mappedObject[ElementMappings.Type__c]; + const propertySet = JSON.parse(mappedObject[ElementMappings.PropertySet__c] || '{}'); + switch (elementType) { + case 'OmniScript': + propertySet['Type'] = this.cleanName(propertySet['Type']); + propertySet['Sub Type'] = this.cleanName(propertySet['Sub Type']); + break; + case 'Integration Procedure Action': + const remoteOptions = propertySet['remoteOptions'] || {}; + remoteOptions['preTransformBundle'] = this.cleanName(remoteOptions['preTransformBundle']); + remoteOptions['postTransformBundle'] = this.cleanName(remoteOptions['postTransformBundle']); + propertySet['remoteOptions'] = remoteOptions; + + propertySet['preTransformBundle'] = this.cleanName(propertySet['preTransformBundle']); + propertySet['postTransformBundle'] = this.cleanName(propertySet['postTransformBundle']); + + // We can't update the IP references, we need to let the user know + const key: String = propertySet['integrationProcedureKey'] || ''; + if (key) { + const parts = key.split('_'); + const newKey = parts.map((p) => this.cleanName(p, true)).join('_'); + if (parts.length > 2) { + invalidIpReferences.set(mappedObject[ElementMappings.Name], key); + } + propertySet['integrationProcedureKey'] = newKey; + } + break; + case 'DataRaptor Turbo Action': + case 'DataRaptor Transform Action': + case 'DataRaptor Post Action': + case 'DataRaptor Extract Action': + propertySet['bundle'] = this.cleanName(propertySet['bundle']); + break; + } + + mappedObject[ElementMappings.PropertySet__c] = JSON.stringify(propertySet); + mappedObject['Name'] = this.cleanName(mappedObject['Name']); + + // BATCH framework requires that each record has an "attributes" property + mappedObject['attributes'] = { + type: OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, + referenceId: elementRecord['Id'], + }; + + return mappedObject; + } + + // Maps an individual Definition into an OmniProcessCompilation record + private mapOsDefinitionsData(osDefinition: AnyJson, omniProcessId: string) { + // Transformed object + const mappedObject = {}; + + // Get the fields of the record + const recordFields = Object.keys(osDefinition); + + // Map individual fields + recordFields.forEach((recordField) => { + const cleanFieldName = this.getCleanFieldName(recordField); + + if (OmniScriptDefinitionMappings.hasOwnProperty(cleanFieldName)) { + mappedObject[OmniScriptDefinitionMappings[cleanFieldName]] = osDefinition[recordField]; + } + }); + + // Set the parent/child relationship + mappedObject[OmniScriptDefinitionMappings.Name] = omniProcessId; + mappedObject[OmniScriptDefinitionMappings.OmniScriptId__c] = omniProcessId; + + let content = mappedObject[OmniScriptDefinitionMappings.Content__c]; + if (content) { + try { + content = JSON.parse(content); + if (content && content['sOmniScriptId']) { + content['sOmniScriptId'] = omniProcessId; + mappedObject[OmniScriptDefinitionMappings.Content__c] = JSON.stringify(content); + } + } catch (ex) { + // Log + } + } + + // BATCH framework requires that each record has an "attributes" property + mappedObject['attributes'] = { + type: OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, + referenceId: osDefinition['Id'], + }; + + return mappedObject; + } + + private getOmniScriptFields(): string[] { + return Object.keys(OmniScriptMappings); + } + + private getElementFields(): string[] { + return Object.keys(ElementMappings); + } + + private getOmniScriptDefinitionFields(): string[] { + return Object.keys(OmniScriptDefinitionMappings); + } + + private sleep() { + return new Promise((resolve) => { + setTimeout(resolve, 5000); + }); + } } export enum OmniScriptExportType { - All, - OS, - IP -} \ No newline at end of file + All, + OS, + IP, +} diff --git a/src/utils/prototypes.ts b/src/utils/prototypes.ts index f580e1f0..f35d468c 100644 --- a/src/utils/prototypes.ts +++ b/src/utils/prototypes.ts @@ -1,19 +1,18 @@ /* eslint-disable */ -String.prototype.formatUnicorn = String.prototype.formatUnicorn || -function () { - "use strict"; +String.prototype.formatUnicorn = + String.prototype.formatUnicorn || + function () { + 'use strict'; var str = this.toString(); if (arguments.length) { - var t = typeof arguments[0]; - var key; - var args = ("string" === t || "number" === t) ? - Array.prototype.slice.call(arguments) - : arguments[0]; + var t = typeof arguments[0]; + var key; + var args = 'string' === t || 'number' === t ? Array.prototype.slice.call(arguments) : arguments[0]; - for (key in args) { - str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]); - } + for (key in args) { + str = str.replace(new RegExp('\\{' + key + '\\}', 'gi'), args[key]); + } } return str; -}; \ No newline at end of file + }; diff --git a/src/utils/query/index.ts b/src/utils/query/index.ts index 40ee91c3..e769b9ff 100644 --- a/src/utils/query/index.ts +++ b/src/utils/query/index.ts @@ -3,179 +3,233 @@ import { AnyJson } from '@salesforce/ts-types'; /* eslint-disable */ export class QueryTools { + public static buildCustomObjectQuery(namespace: string, name: string, fields: string[], filters?: Map) { + const queryFields = this.buildCustomObjectFields(namespace, ['Id', ...fields]); - public static buildCustomObjectQuery(namespace: string, name: string, fields: string[], filters?: Map) { - const queryFields = this.buildCustomObjectFields(namespace, ['Id', ...fields]); + let query = 'SELECT ' + queryFields.join(', ') + ' FROM ' + namespace + '__' + name; - let query = 'SELECT ' + queryFields.join(', ') + ' FROM ' + namespace + '__' + name; + const andFilters = []; + if (filters && filters.size > 0) { + for (let filter of filters.keys()) { + andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); + } - const andFilters = []; - if (filters && filters.size > 0) { - for (let filter of filters.keys()) { - andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); - } - - query += ' WHERE ' + andFilters.join(' AND '); - } - - return query; + query += ' WHERE ' + andFilters.join(' AND '); } - public static buildCustomObjectFields(namespace: string, fields: string[]): string[] { - const queryFields = []; - fields.forEach(field => { - if (field.indexOf('__') > -1) { - queryFields.push(namespace + '__' + field); - } else { - queryFields.push(field); - } + return query; + } + + public static buildCustomObjectFields(namespace: string, fields: string[]): string[] { + const queryFields = []; + fields.forEach((field) => { + if (field.indexOf('__') > -1) { + queryFields.push(namespace + '__' + field); + } else { + queryFields.push(field); + } + }); + + return queryFields; + } + + public static async queryAll( + connection: Connection, + namespace: string, + objectName: string, + fields: string[] + ): Promise { + let allrecords = []; + + const query = QueryTools.buildCustomObjectQuery(namespace, objectName, fields); + + // Execute the query + let results = await connection.query(query); + + if (results && results.totalSize > 0) { + allrecords = results.records; + + // Load more pages + while (results.nextRecordsUrl) { + results = await connection.queryMore(results.nextRecordsUrl); + results.records.forEach((row) => { + allrecords.push(row); }); - - return queryFields; + } } - public static async queryAll(connection: Connection, namespace: string, objectName: string, fields: string[]): Promise { - let allrecords = []; + return allrecords; + } - const query = QueryTools.buildCustomObjectQuery(namespace, objectName, fields); + public static async queryWithFilter( + connection: Connection, + namespace: string, + objectName: string, + fields: string[], + filters?: Map + ): Promise { + let allrecords = []; - // Execute the query - let results = await connection.query(query); + const query = QueryTools.buildCustomObjectQuery(namespace, objectName, fields, filters); - if (results && results.totalSize > 0) { - allrecords = results.records; + // Execute the query + let results = await connection.query(query); - // Load more pages - while (results.nextRecordsUrl) { - results = await connection.queryMore(results.nextRecordsUrl); - results.records.forEach(row => { - allrecords.push(row); - }) - } + if (results && results.totalSize > 0) { + allrecords = results.records; - } + // Load more pages + while (results.nextRecordsUrl) { + results = await connection.queryMore(results.nextRecordsUrl); + results.records.forEach((row) => { + allrecords.push(row); + }); + } + } - return allrecords; + return allrecords; + } + + public static async queryWithFilterAndSort( + connection: Connection, + namespace: string, + objectName: string, + fields: string[], + filters?: Map, + orderBy?: Array + ): Promise { + let allrecords = []; + + let query = QueryTools.buildCustomObjectQuery(namespace, objectName, fields, filters); + if (orderBy && orderBy.length > 0) { + const sortings = []; + for (let ob of orderBy) { + sortings.push(ob.field + ' ' + ob.direction); + } + query += ' ORDER BY ' + sortings.join(', '); } - public static async queryWithFilter(connection: Connection, namespace: string, objectName: string, fields: string[], filters?: Map): Promise { - let allrecords = []; + // Execute the query + let results = await connection.query(query); - const query = QueryTools.buildCustomObjectQuery(namespace, objectName, fields, filters); + if (results && results.totalSize > 0) { + allrecords = results.records; - // Execute the query - let results = await connection.query(query); + // Load more pages + while (results.nextRecordsUrl) { + results = await connection.queryMore(results.nextRecordsUrl); + results.records.forEach((row) => { + allrecords.push(row); + }); + } + } - if (results && results.totalSize > 0) { - allrecords = results.records; + return allrecords; + } + + public static async query( + connection: Connection, + objectName: string, + fields: string[], + filters?: Map, + orderBy?: Array + ) { + let query = 'SELECT ' + fields.join(', ') + ' FROM ' + objectName; + + const andFilters = []; + if (filters && filters.size > 0) { + for (let filter of filters.keys()) { + andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); + } + + query += ' WHERE ' + andFilters.join(' AND '); + } - // Load more pages - while (results.nextRecordsUrl) { - results = await connection.queryMore(results.nextRecordsUrl); - results.records.forEach(row => { - allrecords.push(row); - }) - } + if (orderBy && orderBy.length > 0) { + const sortings = []; + for (let ob of orderBy) { + sortings.push(ob.field + ' ' + ob.direction); + } + query += ' ORDER BY ' + sortings.join(', '); + } - } + // Execute the query + let results = await connection.query(query); - return allrecords; - } + let allrecords = []; + if (results && results.totalSize > 0) { + allrecords = results.records; - public static async query(connection: Connection, objectName: string, fields: string[], filters?: Map, orderBy?: Array) { - let query = 'SELECT ' + fields.join(', ') + ' FROM ' + objectName; - - const andFilters = []; - if (filters && filters.size > 0) { - for (let filter of filters.keys()) { - andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); - } - - query += ' WHERE ' + andFilters.join(' AND '); - } - - if (orderBy && orderBy.length > 0) { - const sortings = []; - for (let ob of orderBy) { - sortings.push(ob.field + ' ' + ob.direction); - } - query += ' ORDER BY ' + sortings.join(', '); - } - - // Execute the query - let results = await connection.query(query); - - let allrecords = []; - if (results && results.totalSize > 0) { - allrecords = results.records; - - // Load more pages - while (results.nextRecordsUrl) { - results = await connection.queryMore(results.nextRecordsUrl); - results.records.forEach(row => { - allrecords.push(row); - }); - } - } - - return allrecords; + // Load more pages + while (results.nextRecordsUrl) { + results = await connection.queryMore(results.nextRecordsUrl); + results.records.forEach((row) => { + allrecords.push(row); + }); + } } - public static async queryIds(connection: Connection, objectName: string, filters?: Map): Promise { - let allrecords = []; - const andFilters = []; - - let query = `SELECT ID FROM ${objectName}`; + return allrecords; + } - if (filters && filters.size > 0) { - for (let filter of filters.keys()) { - andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); - } + public static async queryIds( + connection: Connection, + objectName: string, + filters?: Map + ): Promise { + let allrecords = []; + const andFilters = []; - query += ' WHERE ' + andFilters.join(' AND '); - } + let query = `SELECT ID FROM ${objectName}`; - // Execute the query - let results = await connection.query(query); + if (filters && filters.size > 0) { + for (let filter of filters.keys()) { + andFilters.push(`${filter} = ${QueryTools.getFilterValue(filters.get(filter))}`); + } - if (results && results.totalSize > 0) { - allrecords = results.records; + query += ' WHERE ' + andFilters.join(' AND '); + } - // Load more pages - while (results.nextRecordsUrl) { - results = await connection.queryMore(results.nextRecordsUrl); - results.records.forEach(row => { - allrecords.push(row); - }) - } + // Execute the query + let results = await connection.query(query); - } + if (results && results.totalSize > 0) { + allrecords = results.records; - return allrecords.map(record => record['Id']); + // Load more pages + while (results.nextRecordsUrl) { + results = await connection.queryMore(results.nextRecordsUrl); + results.records.forEach((row) => { + allrecords.push(row); + }); + } } - private static getFilterValue(val: any): string { - switch (typeof val) { - case "bigint": - case "boolean": - case "number": - return `${val}`; - case "function": - return `'${val()}'`; - case "undefined": - return 'NULL'; - case "string": - default: - return `'${val}'`; - } + return allrecords.map((record) => record['Id']); + } + + private static getFilterValue(val: any): string { + switch (typeof val) { + case 'bigint': + case 'boolean': + case 'number': + return `${val}`; + case 'function': + return `'${val()}'`; + case 'undefined': + return 'NULL'; + case 'string': + default: + return `'${val}'`; } + } } export enum SortDirection { - ASC = 'asc', - DESC = 'desc' + ASC = 'asc', + DESC = 'desc', } export interface SortField { - field: string; - direction: SortDirection -} \ No newline at end of file + field: string; + direction: SortDirection; +} diff --git a/test/commands/omnistudio/migration/info.test.ts b/test/commands/omnistudio/migration/info.test.ts index 5230a90c..7ec11c4e 100644 --- a/test/commands/omnistudio/migration/info.test.ts +++ b/test/commands/omnistudio/migration/info.test.ts @@ -19,8 +19,8 @@ describe('omnistudio:migration:info', () => { return Promise.resolve({ records: [] }); }) .stdout() - .command(['omnistudio:migration:info', '--targetusername', 'test@org.com']) - .it('runs omnistudio:migration:info --targetusername test@org.com', (ctx) => { + .command(['omnistudio:migration:info', '--targetusername', 'test@org.com', '--allversions']) + .it('runs omnistudio:migration:info --targetusername test@org.com --allversions', (ctx) => { expect(ctx.stdout).to.contain( 'Hello world! This is org: Super Awesome Org and I will be around until Tue Mar 20 2018!' ); diff --git a/yarn.lock b/yarn.lock index 776be214..42857084 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0": "@ampproject/remapping@^2.1.0": version "2.1.2" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz" @@ -1150,13 +1158,20 @@ dependencies: "@types/node" "*" -"@types/jsforce@^1.11.4", "@types/jsforce@^1.9.41": +"@types/jsforce@^1.11.4": version "1.11.4" resolved "https://registry.yarnpkg.com/@types/jsforce/-/jsforce-1.11.4.tgz#96c484584929e5d8d60afeaab820f767336a29e1" integrity sha512-bgMESDt7cgupb7WM2DtKKEnhHz/aPRSwgz6HyAVmwV1Z2eClARiLJ/pQ7XfytY7Rao3DQKNA8YkUsURF9BR4xQ== dependencies: "@types/node" ">=4.0" +"@types/jsforce@^1.9.41": + version "1.11.3" + resolved "https://registry.yarnpkg.com/@types/jsforce/-/jsforce-1.11.3.tgz#561631e25fb9aa39f30accf26d9e4d9f3fd9924f" + integrity sha512-3M4+uuGaqUQqG+Cb+IDx8xaQIw+s6xW69rvMc7LQm6KzFZtady9KiokNsvyxHwWBrsLJ/PGA10A2N3kMDI6StQ== + dependencies: + "@types/node" ">=4.0" + "@types/json-schema@^7.0.11": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"